summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt25
-rw-r--r--Source/CMakeVersion.cmake6
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx9
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx400
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.h18
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx244
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h22
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.h2
-rw-r--r--Source/CPack/OSXScriptLauncher.cxx122
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx4
-rw-r--r--Source/CPack/cmCPackComponentGroup.h13
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.h6
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.h8
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx4
-rw-r--r--Source/CPack/cmCPackDebGenerator.h6
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx10
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.h5
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx145
-rw-r--r--Source/CPack/cmCPackGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx5
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.h2
-rw-r--r--Source/CPack/cmCPackLog.h5
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx272
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.h39
-rw-r--r--Source/CPack/cmCPackPKGGenerator.cxx48
-rw-r--r--Source/CPack/cmCPackPKGGenerator.h7
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx14
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx5
-rw-r--r--Source/CPack/cmCPackRPMGenerator.h6
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx2
-rw-r--r--Source/CPack/cpack.cxx2
-rw-r--r--Source/CTest/cmCTestBZR.cxx6
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx6
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h3
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx5
-rw-r--r--Source/CTest/cmCTestBuildHandler.h3
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx13
-rw-r--r--Source/CTest/cmCTestGIT.cxx11
-rw-r--r--Source/CTest/cmCTestGenericHandler.h3
-rw-r--r--Source/CTest/cmCTestLaunch.cxx3
-rw-r--r--Source/CTest/cmCTestLaunch.h6
-rw-r--r--Source/CTest/cmCTestLaunchReporter.cxx3
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h2
-rw-r--r--Source/CTest/cmCTestP4.h8
-rw-r--r--Source/CTest/cmCTestRunTest.cxx10
-rw-r--r--Source/CTest/cmCTestRunTest.h3
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx4
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx3
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx33
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h1
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx101
-rw-r--r--Source/CTest/cmCTestTestHandler.h3
-rw-r--r--Source/CTest/cmCTestVC.cxx7
-rw-r--r--Source/CTest/cmCTestVC.h13
-rw-r--r--Source/CTest/cmProcess.cxx2
-rw-r--r--Source/CTest/cmProcess.h18
-rw-r--r--Source/Checks/cm_c11_thread_local.cmake2
-rw-r--r--Source/Checks/cm_cxx14_check.cmake2
-rw-r--r--Source/Checks/cm_cxx17_check.cmake2
-rw-r--r--Source/CursesDialog/ccmake.cxx25
-rw-r--r--Source/CursesDialog/cmCursesForm.cxx29
-rw-r--r--Source/CursesDialog/cmCursesForm.h4
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx14
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx32
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx3
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt2
-rw-r--r--Source/CursesDialog/form/fty_enum.c4
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.cxx115
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.h7
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.in.l11
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx4
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h2
-rw-r--r--Source/QtDialog/QCMake.cxx22
-rw-r--r--Source/QtDialog/QCMake.h12
-rw-r--r--Source/QtDialog/QCMakePreset.h2
-rw-r--r--Source/bindexplib.cxx12
-rw-r--r--Source/bindexplib.h3
-rw-r--r--Source/cmAddCustomCommandCommand.cxx33
-rw-r--r--Source/cmAddCustomTargetCommand.cxx21
-rw-r--r--Source/cmAffinity.cxx2
-rw-r--r--Source/cmBase32.cxx2
-rw-r--r--Source/cmBuildOptions.h44
-rw-r--r--Source/cmCMakePresetsFileInternal.h112
-rw-r--r--Source/cmCMakePresetsFileReadJSON.cxx1032
-rw-r--r--Source/cmCMakePresetsGraph.cxx (renamed from Source/cmCMakePresetsFile.cxx)258
-rw-r--r--Source/cmCMakePresetsGraph.h (renamed from Source/cmCMakePresetsFile.h)113
-rw-r--r--Source/cmCMakePresetsGraphInternal.h163
-rw-r--r--Source/cmCMakePresetsGraphReadJSON.cxx615
-rw-r--r--Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx108
-rw-r--r--Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx228
-rw-r--r--Source/cmCMakePresetsGraphReadJSONTestPresets.cxx360
-rw-r--r--Source/cmCPluginAPI.cxx212
-rw-r--r--Source/cmCTest.cxx49
-rw-r--r--Source/cmCommonTargetGenerator.cxx7
-rw-r--r--Source/cmCommonTargetGenerator.h10
-rw-r--r--Source/cmComputeLinkInformation.cxx17
-rw-r--r--Source/cmComputeLinkInformation.h2
-rw-r--r--Source/cmCoreTryCompile.cxx3
-rw-r--r--Source/cmCustomCommand.cxx77
-rw-r--r--Source/cmCustomCommand.h29
-rw-r--r--Source/cmCustomCommandGenerator.cxx2
-rw-r--r--Source/cmDefinePropertyCommand.cxx97
-rw-r--r--Source/cmDependsCompiler.cxx9
-rw-r--r--Source/cmELF.cxx9
-rw-r--r--Source/cmExecProgramCommand.cxx2
-rw-r--r--Source/cmExecuteProcessCommand.cxx4
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportBuildFileGenerator.cxx19
-rw-r--r--Source/cmExportBuildFileGenerator.h7
-rw-r--r--Source/cmExportFileGenerator.cxx84
-rw-r--r--Source/cmExportFileGenerator.h11
-rw-r--r--Source/cmExportInstallFileGenerator.cxx105
-rw-r--r--Source/cmExportInstallFileGenerator.h6
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx31
-rw-r--r--Source/cmExportTryCompileFileGenerator.h9
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx6
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx3
-rw-r--r--Source/cmFLTKWrapUICommand.cxx25
-rw-r--r--Source/cmFileAPI.cxx3
-rw-r--r--Source/cmFileAPICodemodel.cxx49
-rw-r--r--Source/cmFileAPIToolchains.cxx41
-rw-r--r--Source/cmFileCommand.cxx34
-rw-r--r--Source/cmFileLockResult.cxx2
-rw-r--r--Source/cmFileSet.cxx151
-rw-r--r--Source/cmFileSet.h64
-rw-r--r--Source/cmFileTime.h2
-rw-r--r--Source/cmFindBase.cxx2
-rw-r--r--Source/cmFindCommon.cxx82
-rw-r--r--Source/cmFindCommon.h18
-rw-r--r--Source/cmFindLibraryCommand.cxx3
-rw-r--r--Source/cmFindPackageCommand.cxx89
-rw-r--r--Source/cmFindPackageCommand.h1
-rw-r--r--Source/cmFindPathCommand.cxx14
-rw-r--r--Source/cmFindPathCommand.h3
-rw-r--r--Source/cmFindProgramCommand.cxx23
-rw-r--r--Source/cmFunctionBlocker.cxx2
-rw-r--r--Source/cmGccDepfileLexerHelper.cxx40
-rw-r--r--Source/cmGeneratedFileStream.cxx3
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx8
-rw-r--r--Source/cmGeneratorExpressionNode.cxx11
-rw-r--r--Source/cmGeneratorTarget.cxx932
-rw-r--r--Source/cmGeneratorTarget.h59
-rw-r--r--Source/cmGetPropertyCommand.cxx14
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx7
-rw-r--r--Source/cmGlobVerificationManager.cxx19
-rw-r--r--Source/cmGlobVerificationManager.h6
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx11
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h13
-rw-r--r--Source/cmGlobalGenerator.cxx104
-rw-r--r--Source/cmGlobalGenerator.h9
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx200
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h6
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx13
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h11
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx4
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h7
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx2
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h7
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx16
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h13
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx33
-rw-r--r--Source/cmGlobalNinjaGenerator.h6
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx4
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h4
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx161
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h16
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx13
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h5
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx14
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h1
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx13
-rw-r--r--Source/cmGlobalVisualStudio14Generator.h1
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx14
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h13
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx29
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h19
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx65
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h10
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx13
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx68
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h5
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx260
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h12
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx7
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx74
-rw-r--r--Source/cmGlobalXCodeGenerator.h6
-rw-r--r--Source/cmIDEOptions.cxx6
-rw-r--r--Source/cmInstallCommand.cxx173
-rw-r--r--Source/cmInstallCommandArguments.cxx19
-rw-r--r--Source/cmInstallCommandArguments.h16
-rw-r--r--Source/cmInstallExportGenerator.cxx2
-rw-r--r--Source/cmInstallFileSetGenerator.cxx88
-rw-r--r--Source/cmInstallFileSetGenerator.h52
-rw-r--r--Source/cmLinkItem.cxx4
-rw-r--r--Source/cmLinkItem.h10
-rw-r--r--Source/cmLinkItemGraphVisitor.cxx4
-rw-r--r--Source/cmListCommand.cxx15
-rw-r--r--Source/cmListFileCache.cxx135
-rw-r--r--Source/cmListFileCache.h151
-rw-r--r--Source/cmLoadCommandCommand.cxx1
-rw-r--r--Source/cmLocalGenerator.cxx481
-rw-r--r--Source/cmLocalGenerator.h179
-rw-r--r--Source/cmLocalNinjaGenerator.cxx5
-rw-r--r--Source/cmLocalNinjaGenerator.h4
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx10
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx11
-rw-r--r--Source/cmLocalVisualStudio10Generator.h1
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx77
-rw-r--r--Source/cmLocalVisualStudio7Generator.h2
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx33
-rw-r--r--Source/cmLocalVisualStudioGenerator.h4
-rw-r--r--Source/cmLocalXCodeGenerator.cxx8
-rw-r--r--Source/cmLocalXCodeGenerator.h1
-rw-r--r--Source/cmMachO.cxx8
-rw-r--r--Source/cmMachO.h1
-rw-r--r--Source/cmMacroCommand.cxx2
-rw-r--r--Source/cmMakefile.cxx195
-rw-r--r--Source/cmMakefile.h104
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx12
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx13
-rw-r--r--Source/cmMakefileTargetGenerator.cxx65
-rw-r--r--Source/cmMathCommand.cxx2
-rw-r--r--Source/cmMessenger.cxx81
-rw-r--r--Source/cmMessenger.h11
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx56
-rw-r--r--Source/cmNinjaTargetGenerator.cxx48
-rw-r--r--Source/cmOutputConverter.cxx59
-rw-r--r--Source/cmOutputConverter.h13
-rw-r--r--Source/cmPolicies.cxx2
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Source/cmProjectCommand.cxx7
-rw-r--r--Source/cmPropertyDefinition.cxx17
-rw-r--r--Source/cmPropertyDefinition.h22
-rw-r--r--Source/cmQTWrapCPPCommand.cxx17
-rw-r--r--Source/cmQTWrapUICommand.cxx33
-rw-r--r--Source/cmQtAutoGen.cxx8
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx15
-rw-r--r--Source/cmQtAutoGenInitializer.cxx111
-rw-r--r--Source/cmRulePlaceholderExpander.cxx5
-rw-r--r--Source/cmRulePlaceholderExpander.h1
-rw-r--r--Source/cmSearchPath.cxx63
-rw-r--r--Source/cmSearchPath.h24
-rw-r--r--Source/cmStandardLevelResolver.cxx8
-rw-r--r--Source/cmStandardLexer.h4
-rw-r--r--Source/cmState.cxx26
-rw-r--r--Source/cmState.h13
-rw-r--r--Source/cmStringCommand.cxx2
-rw-r--r--Source/cmSystemTools.cxx54
-rw-r--r--Source/cmSystemTools.h4
-rw-r--r--Source/cmTarget.cxx442
-rw-r--r--Source/cmTarget.h31
-rw-r--r--Source/cmTargetDepend.h2
-rw-r--r--Source/cmTargetExport.h3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx240
-rw-r--r--Source/cmTargetPropCommandBase.cxx4
-rw-r--r--Source/cmTargetPropCommandBase.h6
-rw-r--r--Source/cmTargetPropertyComputer.cxx10
-rw-r--r--Source/cmTargetPropertyComputer.h28
-rw-r--r--Source/cmTargetSourcesCommand.cxx244
-rw-r--r--Source/cmTimestamp.cxx60
-rw-r--r--Source/cmTimestamp.h8
-rw-r--r--Source/cmTransformDepfile.cxx17
-rw-r--r--Source/cmTryRunCommand.cxx2
-rw-r--r--Source/cmVSSetupHelper.cxx130
-rw-r--r--Source/cmVSSetupHelper.h11
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx636
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h22
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx43
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h1
-rw-r--r--Source/cmVisualStudioSlnData.cxx51
-rw-r--r--Source/cmVisualStudioSlnData.h40
-rw-r--r--Source/cmVisualStudioSlnParser.cxx50
-rw-r--r--Source/cmVisualStudioSlnParser.h3
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx6
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.h3
-rw-r--r--Source/cmVsProjectType.h11
-rw-r--r--Source/cmXCOFF.cxx20
-rw-r--r--Source/cmXCOFF.h4
-rw-r--r--Source/cmXCode21Object.h1
-rw-r--r--Source/cmXCodeObject.cxx2
-rw-r--r--Source/cmXCodeObject.h1
-rw-r--r--Source/cmXCodeScheme.cxx22
-rw-r--r--Source/cmXCodeScheme.h9
-rw-r--r--Source/cmXMLParser.h1
-rw-r--r--Source/cmXMLSafe.cxx4
-rw-r--r--Source/cm_codecvt.cxx17
-rw-r--r--Source/cm_codecvt.hxx6
-rw-r--r--Source/cm_utf8.c5
-rw-r--r--Source/cm_utf8.h2
-rw-r--r--Source/cmake.cxx258
-rw-r--r--Source/cmake.h45
-rw-r--r--Source/cmakemain.cxx31
-rw-r--r--Source/cmcldeps.cxx3
-rw-r--r--Source/cmcmd.cxx21
-rw-r--r--Source/kwsys/CMakeLists.txt1
-rw-r--r--Source/kwsys/CTestConfig.cmake4
-rw-r--r--Source/kwsys/Configure.hxx.in14
-rw-r--r--Source/kwsys/Directory.cxx110
-rw-r--r--Source/kwsys/Directory.hxx.in21
-rw-r--r--Source/kwsys/DynamicLoader.cxx25
-rw-r--r--Source/kwsys/DynamicLoader.hxx.in7
-rw-r--r--Source/kwsys/Glob.cxx4
-rw-r--r--Source/kwsys/MD5.c3
-rw-r--r--Source/kwsys/ProcessUNIX.c11
-rw-r--r--Source/kwsys/ProcessWin32.c22
-rw-r--r--Source/kwsys/SharedForward.h.in6
-rw-r--r--Source/kwsys/Status.cxx2
-rw-r--r--Source/kwsys/SystemInformation.cxx66
-rw-r--r--Source/kwsys/SystemTools.cxx161
-rw-r--r--Source/kwsys/SystemTools.hxx.in23
-rw-r--r--Source/kwsys/testDirectory.cxx6
-rw-r--r--Source/kwsys/testDynamicLoader.cxx20
-rw-r--r--Source/kwsys/testDynload.c2
-rw-r--r--Source/kwsys/testDynload.h9
-rw-r--r--Source/kwsys/testEncoding.cxx10
-rw-r--r--Source/kwsys/testSystemTools.cxx42
321 files changed, 9473 insertions, 5211 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index c8498a9..ddcdd7e 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -155,16 +155,20 @@ set(SRCS
cmBinUtilsWindowsPELinker.h
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
+ cmBuildOptions.h
cmCacheManager.cxx
cmCacheManager.h
cmCLocaleEnvironmentScope.h
cmCLocaleEnvironmentScope.cxx
cmCMakePath.h
cmCMakePath.cxx
- cmCMakePresetsFile.cxx
- cmCMakePresetsFile.h
- cmCMakePresetsFileInternal.h
- cmCMakePresetsFileReadJSON.cxx
+ cmCMakePresetsGraph.cxx
+ cmCMakePresetsGraph.h
+ cmCMakePresetsGraphInternal.h
+ cmCMakePresetsGraphReadJSON.cxx
+ cmCMakePresetsGraphReadJSONBuildPresets.cxx
+ cmCMakePresetsGraphReadJSONConfigurePresets.cxx
+ cmCMakePresetsGraphReadJSONTestPresets.cxx
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
@@ -261,6 +265,8 @@ set(SRCS
cmFileLockResult.h
cmFilePathChecksum.cxx
cmFilePathChecksum.h
+ cmFileSet.cxx
+ cmFileSet.h
cmFileTime.cxx
cmFileTime.h
cmFileTimeCache.cxx
@@ -316,6 +322,8 @@ set(SRCS
cmInstallExportGenerator.cxx
cmInstalledFile.h
cmInstalledFile.cxx
+ cmInstallFileSetGenerator.h
+ cmInstallFileSetGenerator.cxx
cmInstallFilesGenerator.h
cmInstallFilesGenerator.cxx
cmInstallImportedRuntimeArtifactsGenerator.h
@@ -762,6 +770,7 @@ if (WIN32)
cmGlobalVisualStudio9Generator.h
cmVisualStudioGeneratorOptions.h
cmVisualStudioGeneratorOptions.cxx
+ cmVsProjectType.h
cmVisualStudio10TargetGenerator.h
cmVisualStudio10TargetGenerator.cxx
cmLocalVisualStudio10Generator.cxx
@@ -1105,7 +1114,6 @@ if(APPLE)
set(CPACK_SRCS ${CPACK_SRCS}
CPack/cmCPackBundleGenerator.cxx
CPack/cmCPackDragNDropGenerator.cxx
- CPack/cmCPackOSXX11Generator.cxx
CPack/cmCPackPKGGenerator.cxx
CPack/cmCPackPackageMakerGenerator.cxx
CPack/cmCPackProductBuildGenerator.cxx
@@ -1142,13 +1150,6 @@ if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARI
add_definitions(-DHAVE_FREEBSD_PKG)
endif()
-if(APPLE)
- add_executable(OSXScriptLauncher
- CPack/OSXScriptLauncher.cxx)
- target_link_libraries(OSXScriptLauncher cmsys)
- target_link_libraries(OSXScriptLauncher "-framework CoreFoundation")
-endif()
-
# Build CMake executable
add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE})
list(APPEND _tools cmake)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 646b63d..7cd4433 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,8 +1,8 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 22)
-set(CMake_VERSION_PATCH 2)
-#set(CMake_VERSION_RC 0)
+set(CMake_VERSION_MINOR 23)
+set(CMake_VERSION_PATCH 0)
+set(CMake_VERSION_RC 2)
set(CMake_VERSION_IS_DIRTY 0)
# Start with the full version number used in tags. It has no dev info.
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
index f6b8a8a..5d995c3 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.cxx
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -29,19 +29,18 @@ cmValue cmCPackIFWCommon::GetOption(const std::string& op) const
bool cmCPackIFWCommon::IsOn(const std::string& op) const
{
- return this->Generator ? this->Generator->cmCPackGenerator::IsOn(op) : false;
+ return this->Generator && this->Generator->cmCPackGenerator::IsOn(op);
}
bool cmCPackIFWCommon::IsSetToOff(const std::string& op) const
{
- return this->Generator ? this->Generator->cmCPackGenerator::IsSetToOff(op)
- : false;
+ return this->Generator && this->Generator->cmCPackGenerator::IsSetToOff(op);
}
bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const
{
- return this->Generator ? this->Generator->cmCPackGenerator::IsSetToEmpty(op)
- : false;
+ return this->Generator &&
+ this->Generator->cmCPackGenerator::IsSetToEmpty(op);
}
bool cmCPackIFWCommon::IsVersionLess(const char* version) const
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index b375ba6..9ca7a69 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -38,202 +38,266 @@ int cmCPackIFWGenerator::PackageFiles()
std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log");
- // Run repogen
- if (!this->Installer.RemoteRepositories.empty()) {
- std::vector<std::string> ifwCmd;
- std::string ifwArg;
+ // Create repositories
+ if (!this->RunRepogen(ifwTmpFile)) {
+ return 0;
+ }
+
+ // Create installer
+ if (!this->RunBinaryCreator(ifwTmpFile)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+std::vector<std::string> cmCPackIFWGenerator::BuildRepogenCommand()
+{
+ std::vector<std::string> ifwCmd;
+ std::string ifwArg;
- ifwCmd.emplace_back(this->RepoGen);
+ ifwCmd.emplace_back(this->RepoGen);
- if (this->IsVersionLess("2.0.0")) {
- ifwCmd.emplace_back("-c");
- ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
+ if (!this->IsVersionLess("4.2")) {
+ if (!this->ArchiveFormat.empty()) {
+ ifwCmd.emplace_back("--archive-format");
+ ifwCmd.emplace_back(this->ArchiveFormat);
+ }
+ if (!this->ArchiveCompression.empty()) {
+ ifwCmd.emplace_back("--compression");
+ ifwCmd.emplace_back(this->ArchiveCompression);
}
+ }
- ifwCmd.emplace_back("-p");
- ifwCmd.emplace_back(this->toplevel + "/packages");
+ if (this->IsVersionLess("2.0.0")) {
+ ifwCmd.emplace_back("-c");
+ ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
+ }
- if (!this->PkgsDirsVector.empty()) {
- for (std::string const& it : this->PkgsDirsVector) {
- ifwCmd.emplace_back("-p");
- ifwCmd.emplace_back(it);
- }
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(this->toplevel + "/packages");
+
+ if (!this->PkgsDirsVector.empty()) {
+ for (std::string const& it : this->PkgsDirsVector) {
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(it);
}
+ }
- if (!this->RepoDirsVector.empty()) {
- if (!this->IsVersionLess("3.1")) {
- for (std::string const& rd : this->RepoDirsVector) {
- ifwCmd.emplace_back("--repository");
- ifwCmd.emplace_back(rd);
- }
- } else {
- cmCPackIFWLogger(WARNING,
- "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
- << "variable is set, but content will be skipped, "
- << "because this feature available only since "
- << "QtIFW 3.1. Please update your QtIFW instance."
- << std::endl);
+ if (!this->RepoDirsVector.empty()) {
+ if (!this->IsVersionLess("3.1")) {
+ for (std::string const& rd : this->RepoDirsVector) {
+ ifwCmd.emplace_back("--repository");
+ ifwCmd.emplace_back(rd);
}
+ } else {
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ << "variable is set, but content will be skipped, "
+ << "because this feature available only since "
+ << "QtIFW 3.1. Please update your QtIFW instance."
+ << std::endl);
}
+ }
- if (!this->OnlineOnly && !this->DownloadedPackages.empty()) {
- ifwCmd.emplace_back("-i");
- auto it = this->DownloadedPackages.begin();
- ifwArg = (*it)->Name;
+ if (!this->OnlineOnly && !this->DownloadedPackages.empty()) {
+ ifwCmd.emplace_back("-i");
+ auto it = this->DownloadedPackages.begin();
+ ifwArg = (*it)->Name;
+ ++it;
+ while (it != this->DownloadedPackages.end()) {
+ ifwArg += "," + (*it)->Name;
++it;
- while (it != this->DownloadedPackages.end()) {
- ifwArg += "," + (*it)->Name;
- ++it;
- }
- ifwCmd.emplace_back(ifwArg);
- }
- ifwCmd.emplace_back(this->toplevel + "/repository");
- cmCPackIFWLogger(VERBOSE,
- "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
- << std::endl);
- std::string output;
- int retVal = 1;
- cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(
- ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
- cmDuration::zero());
- if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile);
- ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
- << std::endl
- << "# Output:" << std::endl
- << output << std::endl;
- cmCPackIFWLogger(
- ERROR,
- "Problem running IFW command: "
- << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
- << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
- return 0;
}
+ ifwCmd.emplace_back(ifwArg);
+ }
+ ifwCmd.emplace_back(this->toplevel + "/repository");
- if (!this->Repository.RepositoryUpdate.empty() &&
- !this->Repository.PatchUpdatesXml()) {
- cmCPackIFWLogger(WARNING,
- "Problem patch IFW \"Updates\" "
- << "file: \"" << this->toplevel
- << "/repository/Updates.xml\"" << std::endl);
- }
+ return ifwCmd;
+}
- cmCPackIFWLogger(OUTPUT,
- "- repository: \"" << this->toplevel
- << "/repository\" generated"
- << std::endl);
+int cmCPackIFWGenerator::RunRepogen(const std::string& ifwTmpFile)
+{
+ if (this->Installer.RemoteRepositories.empty()) {
+ return 1;
+ }
+
+ std::vector<std::string> ifwCmd = this->BuildRepogenCommand();
+ cmCPackIFWLogger(VERBOSE,
+ "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl);
+ std::string output;
+ int retVal = 1;
+ cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
+ bool res = cmSystemTools::RunSingleCommand(ifwCmd, &output, &output, &retVal,
+ nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
+ if (!res || retVal) {
+ cmGeneratedFileStream ofs(ifwTmpFile);
+ ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackIFWLogger(
+ ERROR,
+ "Problem running IFW command: "
+ << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
+ << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
+ return 0;
}
- // Run binary creator
- {
- std::vector<std::string> ifwCmd;
- std::string ifwArg;
+ if (!this->Repository.RepositoryUpdate.empty() &&
+ !this->Repository.PatchUpdatesXml()) {
+ cmCPackIFWLogger(WARNING,
+ "Problem patch IFW \"Updates\" "
+ << "file: \"" << this->toplevel
+ << "/repository/Updates.xml\"" << std::endl);
+ }
- ifwCmd.emplace_back(this->BinCreator);
+ cmCPackIFWLogger(OUTPUT,
+ "- repository: \"" << this->toplevel
+ << "/repository\" generated"
+ << std::endl);
+ return 1;
+}
- ifwCmd.emplace_back("-c");
- ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
+std::vector<std::string> cmCPackIFWGenerator::BuildBinaryCreatorCommmand()
+{
+ std::vector<std::string> ifwCmd;
+ std::string ifwArg;
+
+ ifwCmd.emplace_back(this->BinCreator);
+
+ if (!this->IsVersionLess("4.2")) {
+ if (!this->ArchiveFormat.empty()) {
+ ifwCmd.emplace_back("--archive-format");
+ ifwCmd.emplace_back(this->ArchiveFormat);
+ }
+ if (!this->ArchiveCompression.empty()) {
+ ifwCmd.emplace_back("--compression");
+ ifwCmd.emplace_back(this->ArchiveCompression);
+ }
+ }
+
+ if (!this->IsVersionLess("3.0")) {
+#ifdef __APPLE__
+ // macOS only
+ std::string signingIdentity = this->Installer.SigningIdentity;
+ if (!signingIdentity.empty()) {
+ ifwCmd.emplace_back("--sign");
+ ifwCmd.emplace_back(signingIdentity);
+ }
+#endif
+ }
- if (!this->Installer.Resources.empty()) {
- ifwCmd.emplace_back("-r");
- auto it = this->Installer.Resources.begin();
- std::string path = this->toplevel + "/resources/";
- ifwArg = path + *it;
+ ifwCmd.emplace_back("-c");
+ ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
+
+ if (!this->Installer.Resources.empty()) {
+ ifwCmd.emplace_back("-r");
+ auto it = this->Installer.Resources.begin();
+ std::string path = this->toplevel + "/resources/";
+ ifwArg = path + *it;
+ ++it;
+ while (it != this->Installer.Resources.end()) {
+ ifwArg += "," + path + *it;
++it;
- while (it != this->Installer.Resources.end()) {
- ifwArg += "," + path + *it;
- ++it;
- }
- ifwCmd.emplace_back(ifwArg);
}
+ ifwCmd.emplace_back(ifwArg);
+ }
- ifwCmd.emplace_back("-p");
- ifwCmd.emplace_back(this->toplevel + "/packages");
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(this->toplevel + "/packages");
- if (!this->PkgsDirsVector.empty()) {
- for (std::string const& it : this->PkgsDirsVector) {
- ifwCmd.emplace_back("-p");
- ifwCmd.emplace_back(it);
- }
+ if (!this->PkgsDirsVector.empty()) {
+ for (std::string const& it : this->PkgsDirsVector) {
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(it);
}
+ }
- if (!this->RepoDirsVector.empty()) {
- if (!this->IsVersionLess("3.1")) {
- for (std::string const& rd : this->RepoDirsVector) {
- ifwCmd.emplace_back("--repository");
- ifwCmd.emplace_back(rd);
- }
- } else {
- cmCPackIFWLogger(WARNING,
- "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
- << "variable is set, but content will be skipped, "
- << "because this feature available only since "
- << "QtIFW 3.1. Please update your QtIFW instance."
- << std::endl);
+ if (!this->RepoDirsVector.empty()) {
+ if (!this->IsVersionLess("3.1")) {
+ for (std::string const& rd : this->RepoDirsVector) {
+ ifwCmd.emplace_back("--repository");
+ ifwCmd.emplace_back(rd);
}
+ } else {
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ << "variable is set, but content will be skipped, "
+ << "because this feature available only since "
+ << "QtIFW 3.1. Please update your QtIFW instance."
+ << std::endl);
}
+ }
- if (this->OnlineOnly) {
- ifwCmd.emplace_back("--online-only");
- } else if (!this->DownloadedPackages.empty() &&
- !this->Installer.RemoteRepositories.empty()) {
- ifwCmd.emplace_back("-e");
- auto it = this->DownloadedPackages.begin();
- ifwArg = (*it)->Name;
+ if (this->OnlineOnly) {
+ ifwCmd.emplace_back("--online-only");
+ } else if (!this->DownloadedPackages.empty() &&
+ !this->Installer.RemoteRepositories.empty()) {
+ ifwCmd.emplace_back("-e");
+ auto it = this->DownloadedPackages.begin();
+ ifwArg = (*it)->Name;
+ ++it;
+ while (it != this->DownloadedPackages.end()) {
+ ifwArg += "," + (*it)->Name;
++it;
- while (it != this->DownloadedPackages.end()) {
- ifwArg += "," + (*it)->Name;
- ++it;
- }
- ifwCmd.emplace_back(ifwArg);
- } else if (!this->DependentPackages.empty()) {
- ifwCmd.emplace_back("-i");
- ifwArg.clear();
- // Binary
- auto bit = this->BinaryPackages.begin();
- while (bit != this->BinaryPackages.end()) {
- ifwArg += (*bit)->Name + ",";
- ++bit;
- }
- // Depend
- auto it = this->DependentPackages.begin();
- ifwArg += it->second.Name;
- ++it;
- while (it != this->DependentPackages.end()) {
- ifwArg += "," + it->second.Name;
- ++it;
- }
- ifwCmd.emplace_back(ifwArg);
}
- // TODO: set correct name for multipackages
- if (!this->packageFileNames.empty()) {
- ifwCmd.emplace_back(this->packageFileNames[0]);
- } else {
- ifwCmd.emplace_back("installer" + this->OutputExtension);
+ ifwCmd.emplace_back(ifwArg);
+ } else if (!this->DependentPackages.empty()) {
+ ifwCmd.emplace_back("-i");
+ ifwArg.clear();
+ // Binary
+ auto bit = this->BinaryPackages.begin();
+ while (bit != this->BinaryPackages.end()) {
+ ifwArg += (*bit)->Name + ",";
+ ++bit;
}
- cmCPackIFWLogger(VERBOSE,
- "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
- << std::endl);
- std::string output;
- int retVal = 1;
- cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(
- ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
- cmDuration::zero());
- if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile);
- ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
- << std::endl
- << "# Output:" << std::endl
- << output << std::endl;
- cmCPackIFWLogger(
- ERROR,
- "Problem running IFW command: "
- << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
- << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
- return 0;
+ // Depend
+ auto it = this->DependentPackages.begin();
+ ifwArg += it->second.Name;
+ ++it;
+ while (it != this->DependentPackages.end()) {
+ ifwArg += "," + it->second.Name;
+ ++it;
}
+ ifwCmd.emplace_back(ifwArg);
+ }
+ // TODO: set correct name for multipackages
+ if (!this->packageFileNames.empty()) {
+ ifwCmd.emplace_back(this->packageFileNames[0]);
+ } else {
+ ifwCmd.emplace_back("installer" + this->OutputExtension);
+ }
+
+ return ifwCmd;
+}
+
+int cmCPackIFWGenerator::RunBinaryCreator(const std::string& ifwTmpFile)
+{
+ std::vector<std::string> ifwCmd = this->BuildBinaryCreatorCommmand();
+ cmCPackIFWLogger(VERBOSE,
+ "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl);
+ std::string output;
+ int retVal = 1;
+ cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
+ bool res = cmSystemTools::RunSingleCommand(ifwCmd, &output, &output, &retVal,
+ nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
+ if (!res || retVal) {
+ cmGeneratedFileStream ofs(ifwTmpFile);
+ ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackIFWLogger(
+ ERROR,
+ "Problem running IFW command: "
+ << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
+ << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
+ return 0;
}
return 1;
@@ -323,6 +387,14 @@ int cmCPackIFWGenerator::InitializeInternal()
cmExpandList(dirs, this->RepoDirsVector);
}
+ // Archive format and compression level
+ if (cmValue af = this->GetOption("CPACK_IFW_ARCHIVE_FORMAT")) {
+ this->ArchiveFormat = *af;
+ }
+ if (cmValue ac = this->GetOption("CPACK_IFW_ARCHIVE_COMPRESSION")) {
+ this->ArchiveCompression = *ac;
+ }
+
// Installer
this->Installer.Generator = this;
this->Installer.ConfigureFromOptions();
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
index 024d25d..86b4993 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.h
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -9,13 +9,15 @@
#include <string>
#include <vector>
-#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackIFWCommon.h"
#include "cmCPackIFWInstaller.h"
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
+class cmCPackComponent;
+class cmCPackComponentGroup;
+
/** \class cmCPackIFWGenerator
* \brief A generator for Qt Installer Framework tools
*
@@ -30,8 +32,6 @@ public:
using PackagesMap = std::map<std::string, cmCPackIFWPackage>;
using RepositoriesMap = std::map<std::string, cmCPackIFWRepository>;
- using ComponentsMap = std::map<std::string, cmCPackComponent>;
- using ComponentGoupsMap = std::map<std::string, cmCPackComponentGroup>;
using DependenceMap =
std::map<std::string, cmCPackIFWPackage::DependenceStruct>;
@@ -140,14 +140,22 @@ protected:
std::map<cmCPackComponentGroup*, cmCPackIFWPackage*> GroupPackages;
private:
+ std::vector<std::string> BuildRepogenCommand();
+ int RunRepogen(const std::string& ifwTmpFile);
+
+ std::vector<std::string> BuildBinaryCreatorCommmand();
+ int RunBinaryCreator(const std::string& ifwTmpFile);
+
std::string RepoGen;
std::string BinCreator;
std::string FrameworkVersion;
std::string ExecutableSuffix;
std::string OutputExtension;
+ std::string ArchiveFormat;
+ std::string ArchiveCompression;
- bool OnlineOnly;
- bool ResolveDuplicateNames;
+ bool OnlineOnly{};
+ bool ResolveDuplicateNames{};
std::vector<std::string> PkgsDirsVector;
std::vector<std::string> RepoDirsVector;
};
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 7ee6300..6fc4848 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -254,6 +254,16 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
}
+ // DisableCommandLineInterface
+ if (this->GetOption("CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) {
+ if (this->IsOn("CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) {
+ this->DisableCommandLineInterface = "true";
+ } else if (this->IsSetToOff(
+ "CPACK_IFW_PACKAGE_DISABLE_COMMAND_LINE_INTERFACE")) {
+ this->DisableCommandLineInterface = "false";
+ }
+ }
+
// Space in path
if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
@@ -275,6 +285,34 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
this->Resources.clear();
cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources);
}
+
+ // ProductImages
+ if (cmValue productImages =
+ this->GetOption("CPACK_IFW_PACKAGE_PRODUCT_IMAGES")) {
+ this->ProductImages.clear();
+ cmExpandList(productImages, this->ProductImages);
+ }
+
+ // Run program, run program arguments, and run program description
+ if (cmValue program = this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM")) {
+ this->RunProgram = *program;
+ }
+ if (cmValue arguments =
+ this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM_ARGUMENTS")) {
+ this->RunProgramArguments.clear();
+ cmExpandList(arguments, this->RunProgramArguments);
+ }
+ if (cmValue description =
+ this->GetOption("CPACK_IFW_PACKAGE_RUN_PROGRAM_DESCRIPTION")) {
+ this->RunProgramDescription = *description;
+ }
+
+#ifdef __APPLE__
+ // Code signing identity for signing the generated app bundle
+ if (cmValue id = this->GetOption("CPACK_IFW_PACKAGE_SIGNING_IDENTITY")) {
+ this->SigningIdentity = *id;
+ }
+#endif
}
/** \class cmCPackIFWResourcesParser
@@ -362,29 +400,11 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
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 srcName = cmSystemTools::GetFilenameName(this->Logo);
+ std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
+ std::string name = "cm_logo." + suffix;
std::string path = this->Directory + "/config/" + name;
cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
xout.Element("Logo", name);
@@ -414,42 +434,81 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.Element("Background", name);
}
- // WizardStyle
- if (!this->WizardStyle.empty()) {
- xout.Element("WizardStyle", this->WizardStyle);
- }
+ // Attributes introduced in QtIFW 1.4.0
+ if (!this->IsVersionLess("1.4")) {
+ // ApplicationIcon
+ if (!this->InstallerApplicationIcon.empty()) {
+ std::string srcName =
+ cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
+ std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
+ std::string name = "cm_appicon." + suffix;
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
+ path);
+ // The actual file is looked up by attaching a '.icns' (macOS),
+ // '.ico' (Windows). No functionality on Unix.
+ name = cmSystemTools::GetFilenameWithoutExtension(name);
+ xout.Element("InstallerApplicationIcon", name);
+ }
- // Stylesheet
- if (!this->StyleSheet.empty()) {
- std::string name = cmSystemTools::GetFilenameName(this->StyleSheet);
- std::string path = this->Directory + "/config/" + name;
- cmsys::SystemTools::CopyFileIfDifferent(this->StyleSheet, path);
- xout.Element("StyleSheet", name);
+ // WindowIcon
+ if (!this->InstallerWindowIcon.empty()) {
+ std::string srcName =
+ cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
+ std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
+ std::string name = "cm_winicon." + suffix;
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
+ xout.Element("InstallerWindowIcon", name);
+ }
}
- // WizardDefaultWidth
- if (!this->WizardDefaultWidth.empty()) {
- xout.Element("WizardDefaultWidth", this->WizardDefaultWidth);
- }
+ // Attributes introduced in QtIFW 2.0.0
+ if (!this->IsVersionLess("2.0")) {
+ // WizardDefaultWidth
+ if (!this->WizardDefaultWidth.empty()) {
+ xout.Element("WizardDefaultWidth", this->WizardDefaultWidth);
+ }
- // WizardDefaultHeight
- if (!this->WizardDefaultHeight.empty()) {
- xout.Element("WizardDefaultHeight", this->WizardDefaultHeight);
- }
+ // WizardDefaultHeight
+ if (!this->WizardDefaultHeight.empty()) {
+ xout.Element("WizardDefaultHeight", this->WizardDefaultHeight);
+ }
- // WizardShowPageList
- if (!this->IsVersionLess("4.0") && !this->WizardShowPageList.empty()) {
- xout.Element("WizardShowPageList", this->WizardShowPageList);
- }
+ // Start menu directory
+ if (!this->StartMenuDir.empty()) {
+ xout.Element("StartMenuDir", this->StartMenuDir);
+ }
- // TitleColor
- if (!this->TitleColor.empty()) {
- xout.Element("TitleColor", this->TitleColor);
- }
+ // Maintenance tool
+ if (!this->MaintenanceToolName.empty()) {
+ xout.Element("MaintenanceToolName", this->MaintenanceToolName);
+ }
- // Start menu
- if (!this->IsVersionLess("2.0")) {
- xout.Element("StartMenuDir", this->StartMenuDir);
+ // Maintenance tool ini file
+ if (!this->MaintenanceToolIniFile.empty()) {
+ xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile);
+ }
+
+ 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->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);
+ }
+ } else {
+ // CPack IFW default policy
+ xout.Comment("CPack IFW default policy for QtIFW less 2.0");
+ xout.Element("AllowNonAsciiCharacters", "true");
+ xout.Element("AllowSpaceInPath", "true");
}
// Target dir
@@ -471,41 +530,74 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.EndElement();
}
- // Maintenance tool
- if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) {
- xout.Element("MaintenanceToolName", this->MaintenanceToolName);
+ // Attributes introduced in QtIFW 3.0.0
+ if (!this->IsVersionLess("3.0")) {
+ // WizardStyle
+ if (!this->WizardStyle.empty()) {
+ xout.Element("WizardStyle", this->WizardStyle);
+ }
+
+ // Stylesheet (copy to config dir)
+ if (!this->StyleSheet.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->StyleSheet);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->StyleSheet, path);
+ xout.Element("StyleSheet", name);
+ }
+
+ // TitleColor
+ if (!this->TitleColor.empty()) {
+ xout.Element("TitleColor", this->TitleColor);
+ }
}
- // Maintenance tool ini file
- if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) {
- xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile);
+ // Attributes introduced in QtIFW 4.0.0
+ if (!this->IsVersionLess("4.0")) {
+ // WizardShowPageList
+ if (!this->WizardShowPageList.empty()) {
+ xout.Element("WizardShowPageList", this->WizardShowPageList);
+ }
+
+ // DisableCommandLineInterface
+ if (!this->DisableCommandLineInterface.empty()) {
+ xout.Element("DisableCommandLineInterface",
+ this->DisableCommandLineInterface);
+ }
+
+ // RunProgram
+ if (!this->RunProgram.empty()) {
+ xout.Element("RunProgram", this->RunProgram);
+ }
+
+ // RunProgramArguments
+ if (!this->RunProgramArguments.empty()) {
+ xout.StartElement("RunProgramArguments");
+ for (const auto& arg : this->RunProgramArguments) {
+ xout.Element("Argument", arg);
+ }
+ xout.EndElement();
+ }
+
+ // RunProgramDescription
+ if (!this->RunProgramDescription.empty()) {
+ xout.Element("RunProgramDescription", this->RunProgramDescription);
+ }
}
if (!this->RemoveTargetDir.empty()) {
xout.Element("RemoveTargetDir", this->RemoveTargetDir);
}
- // 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);
+ // Product images (copy to config dir)
+ if (!this->IsVersionLess("4.0") && !this->ProductImages.empty()) {
+ xout.StartElement("ProductImages");
+ for (auto const& srcImg : this->ProductImages) {
+ std::string name = cmSystemTools::GetFilenameName(srcImg);
+ std::string dstImg = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(srcImg, dstImg);
+ xout.Element("Image", name);
}
- }
-
- // 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);
+ xout.EndElement();
}
// Resources (copy to resources dir)
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index a031fc2..205835b 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -109,6 +109,9 @@ public:
/// uninstalling
std::string RemoveTargetDir;
+ /// Set to true if command line interface features should be disabled
+ std::string DisableCommandLineInterface;
+
/// Set to false if the installation path cannot contain space characters
std::string AllowSpaceInPath;
@@ -118,6 +121,25 @@ public:
/// List of resources to include in the installer binary
std::vector<std::string> Resources;
+ /// A list of images to be shown on PerformInstallationPage.
+ std::vector<std::string> ProductImages;
+
+ /// Command executed after the installer is done if the user accepts the
+ /// action
+ std::string RunProgram;
+
+ /// Arguments passed to the program specified in <RunProgram>
+ std::vector<std::string> RunProgramArguments;
+
+ /// Text shown next to the check box for running the program after the
+ /// installation
+ std::string RunProgramDescription;
+
+#ifdef __APPLE__
+ /// Code signing identity for signing the generated app bundle
+ std::string SigningIdentity;
+#endif
+
public:
// Internal implementation
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
index 0cc6f2f..350f6b2 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.h
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -44,7 +44,7 @@ public:
struct DependenceStruct
{
DependenceStruct();
- DependenceStruct(const std::string& dependence);
+ explicit DependenceStruct(const std::string& dependence);
std::string Name;
CompareStruct Compare;
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
deleted file mode 100644
index b7140ab..0000000
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include <cstddef>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include <cm/memory>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "cmsys/FStream.hxx"
-#include "cmsys/Process.h"
-#include "cmsys/SystemTools.hxx"
-
-// For the PATH_MAX constant
-#include <sys/syslimits.h>
-
-#define DebugError(x) \
- ofs << x << std::endl; \
- std::cout << x << std::endl
-
-int main(int argc, char* argv[])
-{
- // if ( cmsys::SystemTools::FileExists(
- cmsys::ofstream ofs("/tmp/output.txt");
-
- CFStringRef fileName;
- CFBundleRef appBundle;
- CFURLRef scriptFileURL;
-
- // get CF URL for script
- if (!(appBundle = CFBundleGetMainBundle())) {
- DebugError("Cannot get main bundle");
- return 1;
- }
- fileName = CFSTR("RuntimeScript");
- if (!(scriptFileURL =
- CFBundleCopyResourceURL(appBundle, fileName, nullptr, nullptr))) {
- DebugError("CFBundleCopyResourceURL failed");
- return 1;
- }
-
- // create path string
- auto path = cm::make_unique<UInt8[]>(PATH_MAX);
- if (!path) {
- 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.get(),
- PATH_MAX)) {
- DebugError("CFURLGetFileSystemRepresentation failed");
- return 1;
- }
-
- // dispose of the CF variable
- CFRelease(scriptFileURL);
-
- std::string fullScriptPath = reinterpret_cast<char*>(path.get());
- path.reset();
-
- if (!cmsys::SystemTools::FileExists(fullScriptPath)) {
- return 1;
- }
-
- 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) {
- args.push_back(argv[cc]);
- }
- args.push_back(nullptr);
-
- cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, args.data());
- cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str());
- cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- cmsysProcess_SetTimeout(cp, 0);
- cmsysProcess_Execute(cp);
-
- char* data;
- int length;
- while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
- // Translate NULL characters in the output into valid text.
- for (int i = 0; i < length; ++i) {
- if (data[i] == '\0') {
- data[i] = ' ';
- }
- }
- std::cout.write(data, length);
- }
-
- cmsysProcess_WaitForExit(cp, nullptr);
-
- bool result = true;
- if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
- if (cmsysProcess_GetExitValue(cp) != 0) {
- result = false;
- }
- } 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) {
- const char* error_str = cmsysProcess_GetErrorString(cp);
- std::cerr << error_str << std::endl;
- result = false;
- } 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);
-
- return !result;
-}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index d03239b..6a0095b 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -219,7 +219,9 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions);
CollectExtensions("CPACK_WIX_CANDLE_EXTENSIONS", this->CandleExtensions);
- this->LightExtensions.insert("WixUIExtension");
+ if (!cmIsOn(GetOption("CPACK_WIX_SKIP_WIX_UI_EXTENSION"))) {
+ this->LightExtensions.insert("WixUIExtension");
+ }
CollectExtensions("CPACK_WIX_EXTENSIONS", this->LightExtensions);
CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions);
CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces);
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index 58377d4..6a47b6d 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -35,12 +35,10 @@ class cmCPackComponent
{
public:
cmCPackComponent()
- : Group(nullptr)
- , IsRequired(true)
+ : IsRequired(true)
, IsHidden(false)
, IsDisabledByDefault(false)
, IsDownloaded(false)
- , TotalSize(0)
{
}
@@ -51,7 +49,7 @@ public:
std::string DisplayName;
/// The component group that contains this component (if any).
- cmCPackComponentGroup* Group;
+ cmCPackComponentGroup* Group = nullptr;
/// Whether this component group must always be installed.
bool IsRequired : 1;
@@ -103,7 +101,7 @@ public:
unsigned long GetInstalledSizeInKbytes(const std::string& installDir) const;
private:
- mutable unsigned long TotalSize;
+ mutable unsigned long TotalSize = 0;
};
/** \class cmCPackComponentGroup
@@ -113,7 +111,8 @@ class cmCPackComponentGroup
{
public:
cmCPackComponentGroup()
- : ParentGroup(nullptr)
+ : IsBold(false)
+ , IsExpandedByDefault(false)
{
}
@@ -136,7 +135,7 @@ public:
std::vector<cmCPackComponent*> Components;
/// The parent group of this component group (if any).
- cmCPackComponentGroup* ParentGroup;
+ cmCPackComponentGroup* ParentGroup = nullptr;
/// The subgroups of this group.
std::vector<cmCPackComponentGroup*> Subgroups;
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index 484db00..fabf4c5 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -17,9 +17,7 @@ cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator()
{
}
-cmCPackCygwinBinaryGenerator::~cmCPackCygwinBinaryGenerator()
-{
-}
+cmCPackCygwinBinaryGenerator::~cmCPackCygwinBinaryGenerator() = default;
int cmCPackCygwinBinaryGenerator::InitializeInternal()
{
@@ -43,7 +41,7 @@ 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());
+ cmGeneratedFileStream ofs(manifestFile);
for (std::string const& file : files) {
// remove the temp dir and replace with /usr
ofs << file.substr(tempdir.size()) << "\n";
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.h b/Source/CPack/cmCPackCygwinBinaryGenerator.h
index f5f7700..ca8e0b5 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.h
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.h
@@ -19,8 +19,8 @@ public:
~cmCPackCygwinBinaryGenerator() override;
protected:
- virtual int InitializeInternal();
- int PackageFiles();
- virtual const char* GetOutputExtension();
+ int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetOutputExtension() override;
std::string OutputExtension;
};
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 59df380..a5863ff 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -26,9 +26,7 @@ cmCPackCygwinSourceGenerator::cmCPackCygwinSourceGenerator()
{
}
-cmCPackCygwinSourceGenerator::~cmCPackCygwinSourceGenerator()
-{
-}
+cmCPackCygwinSourceGenerator::~cmCPackCygwinSourceGenerator() = default;
int cmCPackCygwinSourceGenerator::InitializeInternal()
{
@@ -50,7 +48,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
// Now create a tar file that contains the above .tar.bz2 file
// and the CPACK_CYGWIN_PATCH_FILE and CPACK_TOPLEVEL_DIRECTORY
// files
- std::string compressOutFile = packageDirFileName;
+ const std::string& compressOutFile = packageDirFileName;
// at this point compressOutFile is the full path to
// _CPack_Package/.../package-2.5.0.tar.bz2
// we want to create a tar _CPack_Package/.../package-2.5.0-1-src.tar.bz2
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.h b/Source/CPack/cmCPackCygwinSourceGenerator.h
index 964a4d4..2207bde 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.h
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.h
@@ -19,10 +19,10 @@ public:
~cmCPackCygwinSourceGenerator() override;
protected:
- const char* GetPackagingInstallPrefix();
- virtual int InitializeInternal();
- int PackageFiles();
- virtual const char* GetOutputExtension();
+ const char* GetPackagingInstallPrefix() override;
+ int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetOutputExtension() override;
std::string InstallPrefix;
std::string OutputExtension;
};
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index d7aa287..8e5e637 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -203,7 +203,7 @@ bool DebGenerator::generateDataTar() const
// 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.SetUIDAndGID(0U, 0U);
data_tar.SetUNAMEAndGNAME("root", "root");
// now add all directories which have to be compressed
@@ -902,7 +902,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
}
if (this->componentPackageMethod == ONE_PACKAGE) {
- return std::string("ALL_COMPONENTS_IN_ONE");
+ return { "ALL_COMPONENTS_IN_ONE" };
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index 61a6616..11561a4 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -29,9 +29,9 @@ public:
#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;
+ locations.emplace_back("/sw/bin"); // Fink
+ locations.emplace_back("/opt/local/bin"); // MacPorts
+ return !cmSystemTools::FindProgram("dpkg", locations).empty();
#else
// legacy behavior on other systems
return true;
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 9385a5a..0f7acfb 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -98,7 +98,9 @@ int cmCPackDragNDropGenerator::InitializeInternal()
if (this->IsSet("CPACK_DMG_SLA_DIR")) {
slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR");
- if (!slaDirectory.empty() && this->IsSet("CPACK_RESOURCE_FILE_LICENSE")) {
+ if (!slaDirectory.empty() &&
+ this->IsOn("CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE") &&
+ this->IsSet("CPACK_RESOURCE_FILE_LICENSE")) {
std::string license_file =
this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
if (!license_file.empty() &&
@@ -278,8 +280,10 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
: "HFS+";
// Get optional arguments ...
- std::string cpack_license_file =
- *this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
+ std::string cpack_license_file;
+ if (this->IsOn("CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE")) {
+ cpack_license_file = *this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
+ }
cmValue cpack_dmg_background_image =
this->GetOption("CPACK_DMG_BACKGROUND_IMAGE");
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index 310b0ab..6d1267b 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -4,12 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <sstream>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmCPackGenerator.h"
class cmGeneratedFileStream;
@@ -34,7 +33,7 @@ protected:
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);
+ bool RunCommand(std::ostringstream& command, std::string* output = nullptr);
std::string GetComponentInstallDirNameSuffix(
const std::string& componentName) override;
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index 30b6b0d..b5d41fc 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -21,8 +21,15 @@
#include <sys/stat.h>
+// Suffix used to tell libpkg what compression to use
+static const char FreeBSDPackageCompression[] = "txz";
+// Resulting package file-suffix, for < 1.17 and >= 1.17 versions of libpkg
+static const char FreeBSDPackageSuffix_10[] = ".txz";
+static const char FreeBSDPackageSuffix_17[] = ".pkg";
+
cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr", ".txz")
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr",
+ FreeBSDPackageSuffix_17)
{
}
@@ -35,6 +42,56 @@ int cmCPackFreeBSDGenerator::InitializeInternal()
cmCPackFreeBSDGenerator::~cmCPackFreeBSDGenerator() = default;
+// This is a wrapper for struct pkg_create and pkg_create()
+//
+// Instantiate this class with suitable parameters, then
+// check isValid() to check if it's ok. Afterwards, call
+// Create() to do the actual work. This will leave a package
+// in the given `output_dir`.
+//
+// This wrapper cleans up the struct pkg_create.
+class PkgCreate
+{
+public:
+ PkgCreate()
+ : d(nullptr)
+ {
+ }
+ PkgCreate(const std::string& output_dir, const std::string& toplevel_dir,
+ const std::string& manifest_name)
+ : d(pkg_create_new())
+ , manifest(manifest_name)
+
+ {
+ if (d) {
+ pkg_create_set_format(d, FreeBSDPackageCompression);
+ pkg_create_set_compression_level(d, 0); // Explicitly set default
+ pkg_create_set_overwrite(d, false);
+ pkg_create_set_rootdir(d, toplevel_dir.c_str());
+ pkg_create_set_output_dir(d, output_dir.c_str());
+ }
+ }
+ ~PkgCreate()
+ {
+ if (d)
+ pkg_create_free(d);
+ }
+
+ bool isValid() const { return d; }
+
+ bool Create()
+ {
+ if (!isValid())
+ return false;
+ int r = pkg_create(d, manifest.c_str(), nullptr, false);
+ return r == 0;
+ }
+
+private:
+ struct pkg_create* d;
+ std::string manifest;
+};
+
// This is a wrapper, for use only in stream-based output,
// that will output a string in UCL escaped fashion (in particular,
// quotes and backslashes are escaped). The list of characters
@@ -205,7 +262,7 @@ std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name)
{
cmValue pv = this->GetOption(var_name);
if (!pv) {
- return std::string();
+ return {};
}
return *pv;
}
@@ -271,7 +328,7 @@ void write_manifest_files(cmGeneratedFileStream& s,
s << "\"files\": {\n";
for (std::string const& file : files) {
s << " \"/" << cmSystemTools::RelativePath(toplevel, file) << "\": \""
- << "<sha256>"
+ << "<sha256>" // this gets replaced by libpkg by the actual SHA256
<< "\",\n";
}
s << " },\n";
@@ -281,11 +338,10 @@ int cmCPackFreeBSDGenerator::PackageFiles()
{
if (!this->ReadListFile("Internal/CPack/CPackFreeBSD.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error while execution CPackFreeBSD.cmake" << std::endl);
+ "Error while executing CPackFreeBSD.cmake" << std::endl);
return 0;
}
- std::vector<std::string>::const_iterator fileIt;
cmWorkingDirectory wd(toplevel);
files.erase(std::remove_if(files.begin(), files.end(), ignore_file),
@@ -317,20 +373,85 @@ int cmCPackFreeBSDGenerator::PackageFiles()
ONE_PACKAGE_PER_COMPONENT);
}
+ // There should be one name in the packageFileNames (already, see comment
+ // in cmCPackGenerator::DoPackage(), which holds what CPack guesses
+ // will be the package filename. libpkg does something else, though,
+ // so update the single filename to what we know will be right.
+ if (this->packageFileNames.size() == 1) {
+ std::string currentPackage = this->packageFileNames[0];
+ auto lastSlash = currentPackage.rfind('/');
+
+ // If there is a pathname, preserve that; libpkg will write out
+ // a file with the package name and version as specified in the
+ // manifest, so we look those up (again). lastSlash is the slash
+ // itself, we need that as path separator to the calculated package name.
+ std::string actualPackage =
+ ((lastSlash != std::string::npos)
+ ? std::string(currentPackage, 0, lastSlash + 1)
+ : std::string()) +
+ var_lookup("CPACK_FREEBSD_PACKAGE_NAME") + '-' +
+ var_lookup("CPACK_FREEBSD_PACKAGE_VERSION") + FreeBSDPackageSuffix_17;
+
+ this->packageFileNames.clear();
+ this->packageFileNames.emplace_back(actualPackage);
+ }
+
+ if (!pkg_initialized() && pkg_init(NULL, NULL) != EPKG_OK) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Can not initialize FreeBSD libpkg." << std::endl);
+ return 0;
+ }
+
std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel);
- pkg_create_from_manifest(output_dir.c_str(), ::TXZ, toplevel.c_str(),
- manifestname.c_str(), nullptr);
+ PkgCreate package(output_dir, toplevel, manifestname);
+ if (package.isValid()) {
+ if (!package.Create()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error during pkg_create()" << std::endl);
+ return 0;
+ }
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error before pkg_create()" << std::endl);
+ return 0;
+ }
- std::string broken_suffix =
- cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), ".txz");
+ // Specifically looking for packages suffixed with the TAG, either extension
+ std::string broken_suffix_10 =
+ cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_10);
+ std::string broken_suffix_17 =
+ cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_17);
for (std::string& name : packageFileNames) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl);
- if (cmHasSuffix(name, broken_suffix)) {
- name.replace(name.size() - broken_suffix.size(), std::string::npos,
- ".txz");
+ if (cmHasSuffix(name, broken_suffix_10)) {
+ name.replace(name.size() - broken_suffix_10.size(), std::string::npos,
+ FreeBSDPackageSuffix_10);
+ break;
+ }
+ if (cmHasSuffix(name, broken_suffix_17)) {
+ name.replace(name.size() - broken_suffix_17.size(), std::string::npos,
+ FreeBSDPackageSuffix_17);
break;
}
}
+ // If the name uses a *new* style name, which doesn't exist, but there
+ // is an *old* style name, then use that instead. This indicates we used
+ // an older libpkg, which still creates .txz instead of .pkg files.
+ for (std::string& name : packageFileNames) {
+ if (cmHasSuffix(name, FreeBSDPackageSuffix_17) &&
+ !cmSystemTools::FileExists(name)) {
+ const std::string badSuffix(FreeBSDPackageSuffix_17);
+ const std::string goodSuffix(FreeBSDPackageSuffix_10);
+ std::string repairedName(name);
+ repairedName.replace(repairedName.size() - badSuffix.size(),
+ std::string::npos, goodSuffix);
+ if (cmSystemTools::FileExists(repairedName)) {
+ name = repairedName;
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Repaired packagefile " << name << std::endl);
+ }
+ }
+ }
return 1;
}
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 2f700b4..7ddb103 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -186,7 +186,7 @@ int cmCPackGenerator::InstallProject()
std::string bareTempInstallDirectory =
this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
std::string tempInstallDirectoryStr = bareTempInstallDirectory;
- bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) |
+ bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) ||
cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"));
if (!setDestDir) {
tempInstallDirectoryStr += this->GetPackagingInstallPrefix();
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 79e344b..0b2acca 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -21,7 +21,6 @@
#ifdef __APPLE__
# include "cmCPackBundleGenerator.h"
# include "cmCPackDragNDropGenerator.h"
-# include "cmCPackOSXX11Generator.h"
# include "cmCPackPackageMakerGenerator.h"
# include "cmCPackProductBuildGenerator.h"
#endif
@@ -113,10 +112,6 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("PackageMaker", "Mac OSX Package Maker installer",
cmCPackPackageMakerGenerator::CreateGenerator);
}
- if (cmCPackOSXX11Generator::CanGenerate()) {
- this->RegisterGenerator("OSXX11", "Mac OSX X11 bundle",
- cmCPackOSXX11Generator::CreateGenerator);
- }
if (cmCPackProductBuildGenerator::CanGenerate()) {
this->RegisterGenerator("productbuild", "Mac OSX pkg",
cmCPackProductBuildGenerator::CreateGenerator);
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index 0846573..f3e25a6 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -41,5 +41,5 @@ private:
using t_GeneratorCreatorsMap = std::map<std::string, CreateGeneratorCall*>;
t_GeneratorCreatorsMap GeneratorCreators;
DescriptionsMap GeneratorDescriptions;
- cmCPackLog* Logger;
+ cmCPackLog* Logger{};
};
diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h
index 6cec39c..2ab2f8e 100644
--- a/Source/CPack/cmCPackLog.h
+++ b/Source/CPack/cmCPackLog.h
@@ -4,12 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstring>
#include <memory>
#include <ostream>
#include <string>
-#include <string.h>
-
#define cmCPack_Log(ctSelf, logType, msg) \
do { \
std::ostringstream cmCPackLog_msg; \
@@ -129,7 +128,7 @@ public:
}
const char* Data;
- size_t Length;
+ std::streamsize Length;
};
inline std::ostream& operator<<(std::ostream& os, const cmCPackLogWrite& c)
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index ecc5e08..217f716 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -883,7 +883,7 @@ std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription(
{
// Don't visit a component twice
if (visited.count(component)) {
- return std::string();
+ return {};
}
visited.insert(component);
@@ -907,7 +907,7 @@ std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription(
{
// Don't visit a component twice
if (visited.count(component)) {
- return std::string();
+ return {};
}
visited.insert(component);
@@ -933,7 +933,7 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription(
{
if (group->Components.empty() && group->Subgroups.empty()) {
// Silently skip empty groups. NSIS doesn't support them.
- return std::string();
+ return {};
}
std::string code = "SectionGroup ";
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
deleted file mode 100644
index 7bf1dc7..0000000
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ /dev/null
@@ -1,272 +0,0 @@
-/* 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 <sstream>
-
-#include "cm_sys_stat.h"
-
-#include "cmCPackGenerator.h"
-#include "cmCPackLog.h"
-#include "cmDuration.h"
-#include "cmGeneratedFileStream.h"
-#include "cmStringAlgorithms.h"
-#include "cmSystemTools.h"
-#include "cmValue.h"
-
-cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default;
-
-cmCPackOSXX11Generator::~cmCPackOSXX11Generator() = default;
-
-int cmCPackOSXX11Generator::PackageFiles()
-{
- // TODO: Use toplevel ?
- // It is used! Is this an obsolete comment?
-
- cmValue cpackPackageExecutables =
- this->GetOption("CPACK_PACKAGE_EXECUTABLES");
- if (cpackPackageExecutables) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "The cpackPackageExecutables: " << cpackPackageExecutables
- << "." << std::endl);
- std::ostringstream str;
- std::ostringstream deleteStr;
- std::vector<std::string> cpackPackageExecutablesVector =
- cmExpandedList(cpackPackageExecutables);
- if (cpackPackageExecutablesVector.size() % 2 != 0) {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR,
- "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
- "<icon name>."
- << std::endl);
- return 0;
- }
- std::vector<std::string>::iterator it;
- for (it = cpackPackageExecutablesVector.begin();
- it != cpackPackageExecutablesVector.end(); ++it) {
- std::string cpackExecutableName = *it;
- ++it;
- this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME", cpackExecutableName);
- }
- }
-
- // Disk image directories
- std::string diskImageDirectory = toplevel;
- std::string diskImageBackgroundImageDir =
- diskImageDirectory + "/.background";
-
- // App bundle directories
- std::string packageDirFileName = cmStrCat(
- toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app");
- std::string contentsDirectory = packageDirFileName + "/Contents";
- std::string resourcesDirectory = contentsDirectory + "/Resources";
- std::string appDirectory = contentsDirectory + "/MacOS";
- std::string scriptDirectory = resourcesDirectory + "/Scripts";
- std::string resourceFileName =
- cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc");
-
- const char* dir = resourcesDirectory.c_str();
- const char* appdir = appDirectory.c_str();
- const char* scrDir = scriptDirectory.c_str();
- const char* contDir = contentsDirectory.c_str();
- const char* rsrcFile = resourceFileName.c_str();
- cmValue iconFile = this->GetOption("CPACK_PACKAGE_ICON");
- 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);
- return 0;
- }
- std::string destFileName = resourcesDirectory + "/" + iconFileName;
- this->ConfigureFile(iconFile, destFileName, true);
- this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName);
- }
-
- std::string applicationsLinkName = diskImageDirectory + "/Applications";
- cmSystemTools::CreateSymlink("/Applications", applicationsLinkName);
-
- 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").GetCStr(), true)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem copying the resource files" << std::endl);
- return 0;
- }
-
- // Two of the files need to have execute permission, so ensure they do:
- std::string runTimeScript = cmStrCat(dir, "/RuntimeScript");
-
- std::string appScriptName =
- cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
-
- mode_t 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);
- }
-
- 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);
- }
-
- std::string output;
- std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
- "/hdiutilOutput.log");
- std::ostringstream dmgCmd;
- dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
- << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
- << diskImageDirectory << "\" \"" << packageFileNames[0] << "\"";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Compress disk image using command: " << dmgCmd.str()
- << std::endl);
- // since we get random dashboard failures with this one
- // try running it more than once
- int retVal = 1;
- int numTries = 10;
- bool res = false;
- while (numTries > 0) {
- res = cmSystemTools::RunSingleCommand(
- dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
- cmDuration::zero());
- if (res && !retVal) {
- numTries = -1;
- break;
- }
- cmSystemTools::Delay(500);
- numTries--;
- }
- if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile);
- ofs << "# Run command: " << dmgCmd.str() << std::endl
- << "# Output:" << std::endl
- << output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running hdiutil command: "
- << dmgCmd.str() << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
- return 0;
- }
-
- return 1;
-}
-
-int cmCPackOSXX11Generator::InitializeInternal()
-{
- cmCPackLogger(cmCPackLog::LOG_WARNING,
- "The OSXX11 generator is deprecated "
- "and will be removed in a future version.\n");
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "cmCPackOSXX11Generator::Initialize()" << std::endl);
- std::vector<std::string> path;
- std::string pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
- if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find hdiutil compiler" << std::endl);
- return 0;
- }
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath);
-
- return this->Superclass::InitializeInternal();
-}
-
-/*
-bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name)
-{
- 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 = cmStrCat(
-this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext );
-
-
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << (inFileName ? inFileName : "(NULL)")
- << " to " << destFileName << std::endl);
- this->ConfigureFile(inFileName, destFileName);
- return true;
-}
-*/
-
-bool cmCPackOSXX11Generator::CopyResourcePlistFile(
- const std::string& name, const std::string& dir,
- const char* outputFileName /* = 0 */, bool copyOnly /* = false */)
-{
- std::string inFName = cmStrCat("CPack.", name, ".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;
- }
-
- if (!outputFileName) {
- outputFileName = name.c_str();
- }
-
- std::string destFileName = cmStrCat(dir, '/', outputFileName);
-
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Configure file: " << inFileName << " to " << destFileName
- << std::endl);
- this->ConfigureFile(inFileName, destFileName, copyOnly);
- return true;
-}
-
-const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
-{
- this->InstallPrefix =
- cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- ".app/Contents/Resources");
- return this->InstallPrefix.c_str();
-}
diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h
deleted file mode 100644
index 8fae136..0000000
--- a/Source/CPack/cmCPackOSXX11Generator.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#pragma once
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <string>
-
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackOSXX11Generator
- * \brief A generator for OSX X11 modules
- *
- * Based on Gimp.app
- */
-class cmCPackOSXX11Generator : public cmCPackGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackOSXX11Generator, cmCPackGenerator);
-
- /**
- * Construct generator
- */
- cmCPackOSXX11Generator();
- ~cmCPackOSXX11Generator() override;
-
-protected:
- virtual int InitializeInternal() override;
- int PackageFiles() override;
- const char* GetPackagingInstallPrefix() override;
- const char* GetOutputExtension() override { return ".dmg"; }
-
- // bool CopyCreateResourceFile(const std::string& name,
- // const std::string& dir);
- 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
index 91adf32..d8095cc 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -162,6 +162,8 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
CreateChoice(PostFlightComponent, xout);
}
+ this->CreateDomains(xout);
+
// default background
this->CreateBackground(nullptr, metapackageFile, genName, xout);
// Dark Aqua
@@ -210,9 +212,14 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
cmXMLWriter& xout)
{
- std::string packageId =
- cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
- this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
+ std::string packageId;
+ if (cmValue i = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER")) {
+ packageId = cmStrCat(i, '.', component.Name);
+ } else {
+ packageId =
+ cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+ this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
+ }
xout.StartElement("choice");
xout.Attribute("id", component.Name + "Choice");
@@ -268,7 +275,10 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
xout.Attribute("id", packageId);
xout.Attribute("version", this->GetOption("CPACK_PACKAGE_VERSION"));
xout.Attribute("installKBytes", installedSize);
- xout.Attribute("auth", "Admin");
+ // The auth attribute is deprecated in favor of the domains element
+ if (cmIsOff(this->GetOption("CPACK_PRODUCTBUILD_DOMAINS"))) {
+ xout.Attribute("auth", "Admin");
+ }
xout.Attribute("onConclusion", "None");
if (component.IsDownloaded) {
xout.Content(this->GetOption("CPACK_DOWNLOAD_SITE"));
@@ -281,6 +291,36 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
xout.EndElement(); // pkg-ref
}
+void cmCPackPKGGenerator::CreateDomains(cmXMLWriter& xout)
+{
+ std::string opt = "CPACK_PRODUCTBUILD_DOMAINS";
+ if (cmIsOff(this->GetOption(opt))) {
+ return;
+ }
+
+ xout.StartElement("domains");
+
+ // Product can be installed at the root of any volume by default
+ // unless specified
+ cmValue param = this->GetOption(cmStrCat(opt, "_ANYWHERE"));
+ xout.Attribute("enable_anywhere",
+ (param && cmIsOff(param)) ? "false" : "true");
+
+ // Product cannot be installed into the current user's home directory
+ // by default unless specified
+ param = this->GetOption(cmStrCat(opt, "_USER"));
+ xout.Attribute("enable_currentUserHome",
+ (param && cmIsOn(param)) ? "true" : "false");
+
+ // Product can be installed into the root directory by default
+ // unless specified
+ param = this->GetOption(cmStrCat(opt, "_ROOT"));
+ xout.Attribute("enable_localSystem",
+ (param && cmIsOff(param)) ? "false" : "true");
+
+ xout.EndElement();
+}
+
void cmCPackPKGGenerator::AddDependencyAttributes(
const cmCPackComponent& component,
std::set<const cmCPackComponent*>& visited, std::ostringstream& out)
diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h
index 17cdcdf..256b334 100644
--- a/Source/CPack/cmCPackPKGGenerator.h
+++ b/Source/CPack/cmCPackPKGGenerator.h
@@ -43,7 +43,8 @@ protected:
// 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);
+ bool CopyResourcePlistFile(const std::string& name,
+ const char* outName = nullptr);
int CopyInstallScript(const std::string& resdir, const std::string& script,
const std::string& name);
@@ -90,6 +91,10 @@ protected:
void CreateBackground(const char* themeName, const char* metapackageFile,
cm::string_view genName, cmXMLWriter& xout);
+ /// Create the "domains" XML element to indicate where the product can
+ /// be installed
+ void CreateDomains(cmXMLWriter& xout);
+
// The PostFlight component when creating a metapackage
cmCPackComponent PostFlightComponent;
};
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index f55b8de..4ad616d 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -95,6 +95,10 @@ int cmCPackProductBuildGenerator::PackageFiles()
if (cmValue p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
keychainPath = p;
}
+ std::string identifier;
+ if (cmValue i = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER")) {
+ identifier = i;
+ }
pkgCmd << productbuild << " --distribution \"" << packageDirFileName
<< "/Contents/distribution.dist\""
@@ -102,6 +106,7 @@ int cmCPackProductBuildGenerator::PackageFiles()
<< "\""
<< " --resources \"" << resDir << "\""
<< " --version \"" << version << "\""
+ << (identifier.empty() ? "" : " --identifier \"" + identifier + "\"")
<< (identityName.empty() ? "" : " --sign \"" + identityName + "\"")
<< (keychainPath.empty() ? ""
: " --keychain \"" + keychainPath + "\"")
@@ -204,8 +209,13 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
// The command that will be used to run ProductBuild
std::ostringstream pkgCmd;
- std::string pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"),
- '.', this->GetOption("CPACK_PACKAGE_NAME"));
+ std::string pkgId;
+ if (cmValue n = this->GetOption("CPACK_PRODUCTBUILD_IDENTIFIER")) {
+ pkgId = n;
+ } else {
+ pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+ this->GetOption("CPACK_PACKAGE_NAME"));
+ }
if (component) {
pkgId += '.';
pkgId += component->Name;
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 9e50700..3d4d05e 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -329,9 +329,10 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
if (retval) {
this->AddGeneratedPackageNames();
+ return retval;
}
- return retval;
+ return 0;
}
int cmCPackRPMGenerator::PackageComponentsAllInOne(
@@ -424,7 +425,7 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
}
if (this->componentPackageMethod == ONE_PACKAGE) {
- return std::string("ALL_COMPONENTS_IN_ONE");
+ return { "ALL_COMPONENTS_IN_ONE" };
}
// We have to find the name of the COMPONENT GROUP
// the current COMPONENT belongs to.
diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h
index 0288f2f..886afb1 100644
--- a/Source/CPack/cmCPackRPMGenerator.h
+++ b/Source/CPack/cmCPackRPMGenerator.h
@@ -32,9 +32,9 @@ public:
#ifdef __APPLE__
// on MacOS enable CPackRPM iff rpmbuild is found
std::vector<std::string> locations;
- locations.push_back("/sw/bin"); // Fink
- locations.push_back("/opt/local/bin"); // MacPorts
- return cmSystemTools::FindProgram("rpmbuild") != "" ? true : false;
+ locations.emplace_back("/sw/bin"); // Fink
+ locations.emplace_back("/opt/local/bin"); // MacPorts
+ return !cmSystemTools::FindProgram("rpmbuild").empty();
#else
// legacy behavior on other systems
return true;
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 1340fb5..6ad3755 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -107,7 +107,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Number of lines: " << counter << std::endl);
char buffer[1024];
- sprintf(buffer, "%d", counter);
+ snprintf(buffer, sizeof(buffer), "%d", counter);
cmSystemTools::ReplaceString(res, headerLengthTag, buffer);
// Write in file
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 54fd358..f43642f 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -67,7 +67,7 @@ struct cpackDefinitions
{
using MapType = std::map<std::string, std::string>;
MapType Map;
- cmCPackLog* Log;
+ cmCPackLog* Log{};
};
int cpackDefinitionArgument(const char* argument, const char* cValue,
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index a353435..0fe4ff4 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -20,9 +20,9 @@
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-extern "C" int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/,
- const XML_Char* name,
- XML_Encoding* info)
+static int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/,
+ const XML_Char* name,
+ XML_Encoding* info)
{
static const int latin1[] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index adfc8ef..e09b4dd 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -9,6 +9,7 @@
#include "cmsys/Process.h"
+#include "cmBuildOptions.h"
#include "cmCTest.h"
#include "cmCTestTestHandler.h"
#include "cmGlobalGenerator.h"
@@ -263,10 +264,13 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
if (!config) {
config = "Debug";
}
+
+ cmBuildOptions buildOptions(!this->BuildNoClean, false,
+ PackageResolveMode::Disable);
int retVal = cm.GetGlobalGenerator()->Build(
cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
this->BuildProject, { tar }, output, this->BuildMakeProgram, config,
- !this->BuildNoClean, false, false, remainingTime);
+ buildOptions, false, remainingTime);
out << output;
// if the build failed then return
if (retVal) {
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index b9cc35c..e022e68 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -4,12 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <sstream>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmCTestGenericHandler.h"
#include "cmDuration.h"
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index f9c4a8e..2aba79d 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -81,6 +81,7 @@ static const char* cmCTestErrorMatches[] = {
"^The project cannot be built\\.",
"^\\[ERROR\\]",
"^Command .* failed with exit code",
+ "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): (error|ошибка)",
nullptr
};
@@ -122,6 +123,7 @@ static const char* cmCTestWarningMatches[] = {
"cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*",
"^CMake Warning.*:",
"^\\[WARNING\\]",
+ "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): (warning|предупреждение)",
nullptr
};
@@ -160,6 +162,9 @@ static cmCTestBuildCompileErrorWarningRex cmCTestWarningErrorFileLine[] = {
{ "^([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 },
+ { "lcc: \"([^\"]+)\", (line|строка) ([0-9]+): "
+ "(error|ошибка|warning|предупреждение)",
+ 1, 3 },
{ nullptr, 0, 0 }
};
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 58e8d9c..e33294d 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -5,13 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <chrono>
+#include <cstddef>
#include <deque>
#include <iosfwd>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmsys/RegularExpression.hxx"
#include "cmCTestGenericHandler.h"
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 57b1dda..1b2f769 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -49,9 +49,8 @@ public:
}
~cmCTestRunProcess()
{
- if (!(this->PipeState == -1) &&
- !(this->PipeState == cmsysProcess_Pipe_None) &&
- !(this->PipeState == cmsysProcess_Pipe_Timeout)) {
+ if (this->PipeState != -1 && this->PipeState != cmsysProcess_Pipe_None &&
+ this->PipeState != cmsysProcess_Pipe_Timeout) {
this->WaitForExit();
}
cmsysProcess_Delete(this->Process);
@@ -148,7 +147,8 @@ bool cmCTestCoverageHandler::StartCoverageLogFile(
cmGeneratedFileStream& covLogFile, int logFileCount)
{
char covLogFilename[1024];
- sprintf(covLogFilename, "CoverageLog-%d", logFileCount);
+ snprintf(covLogFilename, sizeof(covLogFilename), "CoverageLog-%d",
+ logFileCount);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Open file: " << covLogFilename << std::endl,
this->Quiet);
@@ -165,7 +165,8 @@ void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
int logFileCount)
{
char covLogFilename[1024];
- sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount);
+ snprintf(covLogFilename, sizeof(covLogFilename), "CoverageLog-%d.xml",
+ logFileCount);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Close file: " << covLogFilename << std::endl,
this->Quiet);
@@ -692,7 +693,7 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf)
# define fnc_prefix(s, t) cmHasPrefix(s, t)
#endif
-bool IsFileInDir(const std::string& infile, const std::string& indir)
+static bool IsFileInDir(const std::string& infile, const std::string& indir)
{
std::string file = cmSystemTools::CollapseFullPath(infile);
std::string dir = cmSystemTools::CollapseFullPath(indir);
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index d85edcc..56f805c 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -24,7 +24,7 @@ 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 epic * 10000000 + major * 100000 + minor * 1000 + fix;
}
cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log)
@@ -582,16 +582,17 @@ private:
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);
+ snprintf(dt, sizeof(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) {
- sprintf(tz, " +%04ld", person.TimeZone);
+ snprintf(tz, sizeof(tz), " +%04ld", person.TimeZone);
} else {
- sprintf(tz, " -%04ld", -person.TimeZone);
+ snprintf(tz, sizeof(tz), " -%04ld", -person.TimeZone);
}
out += tz;
return out;
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index b4b0ad8..4bdb9c2 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -4,12 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <map>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmValue.h"
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 15c443a..4a33869 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -20,9 +20,10 @@
#include "cmake.h"
#ifdef _WIN32
+# include <cstdio> // for std{out,err} and fileno
+
# include <fcntl.h> // for _O_BINARY
# include <io.h> // for _setmode
-# include <stdio.h> // for std{out,err} and fileno
#endif
cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index eabb608..c5a6476 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -24,14 +24,14 @@ public:
/** Entry point from ctest executable main(). */
static int Main(int argc, const char* const argv[]);
+ cmCTestLaunch(const cmCTestLaunch&) = delete;
+ cmCTestLaunch& operator=(const cmCTestLaunch&) = delete;
+
private:
// Initialize the launcher from its command line.
cmCTestLaunch(int argc, const char* const* argv);
~cmCTestLaunch();
- cmCTestLaunch(const cmCTestLaunch&) = delete;
- cmCTestLaunch& operator=(const cmCTestLaunch&) = delete;
-
// Run the real command.
int Run();
void RunChild();
diff --git a/Source/CTest/cmCTestLaunchReporter.cxx b/Source/CTest/cmCTestLaunchReporter.cxx
index 5334a93..149ba5d 100644
--- a/Source/CTest/cmCTestLaunchReporter.cxx
+++ b/Source/CTest/cmCTestLaunchReporter.cxx
@@ -13,9 +13,10 @@
#include "cmXMLWriter.h"
#ifdef _WIN32
+# include <cstdio> // for std{out,err} and fileno
+
# include <fcntl.h> // for _O_BINARY
# include <io.h> // for _setmode
-# include <stdio.h> // for std{out,err} and fileno
#endif
cmCTestLaunchReporter::cmCTestLaunchReporter()
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 5de42f9..2f5ad40 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <map>
#include <memory>
#include <set>
@@ -11,7 +12,6 @@
#include <vector>
#include <cm3p/uv.h>
-#include <stddef.h>
#include "cmCTest.h"
#include "cmCTestResourceAllocator.h"
diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h
index d03f9cb..1889520 100644
--- a/Source/CTest/cmCTestP4.h
+++ b/Source/CTest/cmCTestP4.h
@@ -34,14 +34,6 @@ private:
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;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 9d2cef6..6cd3b09 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -229,7 +229,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
- sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count());
+ snprintf(buf, sizeof(buf), "%6.2f sec",
+ this->TestProcess->GetTotalTime().count());
outputStream << buf << "\n";
bool passedOrSkipped = passed || skipped;
@@ -294,9 +295,10 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
ttime -= minutes;
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(ttime);
char buffer[100];
- sprintf(buffer, "%02d:%02d:%02d", static_cast<unsigned>(hours.count()),
- static_cast<unsigned>(minutes.count()),
- static_cast<unsigned>(seconds.count()));
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d",
+ static_cast<unsigned>(hours.count()),
+ static_cast<unsigned>(minutes.count()),
+ static_cast<unsigned>(seconds.count()));
*this->TestHandler->LogFile
<< "----------------------------------------------------------"
<< std::endl;
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 2082156..7a97fa9 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -4,14 +4,13 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestTestHandler.h"
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index f685f66..16c0a0e 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -48,8 +48,6 @@
# include <unistd.h>
#endif
-#define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log"
-
cmCTestScriptHandler::cmCTestScriptHandler() = default;
void cmCTestScriptHandler::Initialize()
@@ -411,7 +409,7 @@ int cmCTestScriptHandler::ExtractVariables()
char updateVar[40];
int i;
for (i = 1; i < 10; ++i) {
- sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i);
+ snprintf(updateVar, sizeof(updateVar), "CTEST_EXTRA_UPDATES_%i", i);
cmValue updateVal = this->Makefile->GetDefinition(updateVar);
if (updateVal) {
if (this->UpdateCmd.empty()) {
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index c4f87e9..a2dc615 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -58,6 +58,9 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "SubmitInactivityTimeout",
+ "CTEST_SUBMIT_INACTIVITY_TIMEOUT", this->Quiet);
cmValue notesFilesVariable =
this->Makefile->GetDefinition("CTEST_NOTES_FILES");
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index b99bb79..fae5e30 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -7,6 +7,7 @@
#include <cstdlib>
#include <sstream>
+#include <cm/iomanip>
#include <cmext/algorithm>
#include <cm3p/curl/curl.h>
@@ -216,8 +217,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(
// 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);
+ auto submitInactivityTimeout = this->GetSubmitInactivityTimeout();
+ if (submitInactivityTimeout != 0) {
+ ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
+ submitInactivityTimeout);
+ }
/* HTTP PUT please */
::curl_easy_setopt(curl, CURLOPT_PUT, 1);
@@ -499,7 +503,10 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
std::vector<std::string> args = cmExpandedList(curlopt);
curl.SetCurlOptions(args);
- curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
+ auto submitInactivityTimeout = this->GetSubmitInactivityTimeout();
+ if (submitInactivityTimeout != 0) {
+ curl.SetTimeOutSeconds(submitInactivityTimeout);
+ }
curl.SetHttpHeaders(this->HttpHeaders);
std::string url = this->CTest->GetSubmitURL();
if (!cmHasLiteralPrefix(url, "http://") &&
@@ -893,6 +900,26 @@ void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
}
}
+int cmCTestSubmitHandler::GetSubmitInactivityTimeout()
+{
+ int submitInactivityTimeout = SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT;
+ std::string const& timeoutStr =
+ this->CTest->GetCTestConfiguration("SubmitInactivityTimeout");
+ if (!timeoutStr.empty()) {
+ unsigned long timeout;
+ if (cmStrToULong(timeoutStr, &timeout)) {
+ submitInactivityTimeout = static_cast<int>(timeout);
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "SubmitInactivityTimeout is invalid: "
+ << cm::quoted(timeoutStr) << "."
+ << " Using a default value of "
+ << SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT << "." << std::endl);
+ }
+ }
+ return submitInactivityTimeout;
+}
+
void cmCTestSubmitHandler::SelectFiles(std::set<std::string> const& files)
{
this->Files.insert(files.begin(), files.end());
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index 809c615..0c7253c 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -63,6 +63,7 @@ private:
void ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk);
std::string GetSubmitResultsPrefix();
+ int GetSubmitInactivityTimeout();
class ResponseParser;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 6e97a83..5a3a8d0 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -59,6 +59,8 @@ public:
}
virtual ~cmCTestCommand() = default;
+ cmCTestCommand(const cmCTestCommand&) = default;
+ cmCTestCommand& operator=(const cmCTestCommand&) = default;
bool operator()(std::vector<cmListFileArgument> const& args,
cmExecutionStatus& status)
@@ -79,6 +81,42 @@ public:
cmCTestTestHandler* TestHandler;
};
+bool ReadSubdirectory(std::string fname, cmExecutionStatus& status)
+{
+ if (!cmSystemTools::FileExists(fname)) {
+ // No subdirectory? So what...
+ return true;
+ }
+ bool readit = false;
+ {
+ cmWorkingDirectory workdir(fname);
+ if (workdir.Failed()) {
+ status.SetError("Failed to change directory to " + fname + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return false;
+ }
+ const char* testFilename;
+ if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
+ // does the CTestTestfile.cmake exist ?
+ testFilename = "CTestTestfile.cmake";
+ } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
+ // does the DartTestfile.txt exist ?
+ testFilename = "DartTestfile.txt";
+ } else {
+ // No CTestTestfile? Who cares...
+ return true;
+ }
+ fname += "/";
+ fname += testFilename;
+ readit = status.GetMakefile().ReadDependentFile(fname);
+ }
+ if (!readit) {
+ status.SetError(cmStrCat("Could not find include file: ", fname));
+ return false;
+ }
+ return true;
+}
+
bool cmCTestSubdirCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -96,35 +134,7 @@ bool cmCTestSubdirCommand(std::vector<std::string> const& args,
fname = cmStrCat(cwd, '/', arg);
}
- if (!cmSystemTools::FileIsDirectory(fname)) {
- // No subdirectory? So what...
- continue;
- }
- bool readit = false;
- {
- cmWorkingDirectory workdir(fname);
- if (workdir.Failed()) {
- status.SetError("Failed to change directory to " + fname + " : " +
- std::strerror(workdir.GetLastResult()));
- return false;
- }
- const char* testFilename;
- if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
- // does the CTestTestfile.cmake exist ?
- 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;
- readit = status.GetMakefile().ReadDependentFile(fname);
- }
- if (!readit) {
- status.SetError(cmStrCat("Could not load include file: ", fname));
+ if (!ReadSubdirectory(std::move(fname), status)) {
return false;
}
}
@@ -142,32 +152,7 @@ bool cmCTestAddSubdirectoryCommand(std::vector<std::string> const& args,
std::string fname =
cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]);
- if (!cmSystemTools::FileExists(fname)) {
- // 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;
- }
- fname += "/";
- fname += testFilename;
- readit = status.GetMakefile().ReadDependentFile(fname);
- }
- if (!readit) {
- status.SetError(cmStrCat("Could not find include file: ", fname));
- return false;
- }
- return true;
+ return ReadSubdirectory(std::move(fname), status);
}
class cmCTestAddTestCommand : public cmCTestCommand
@@ -621,7 +606,7 @@ void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed,
this->PrintLabelOrSubprojectSummary(false);
}
char realBuf[1024];
- sprintf(realBuf, "%6.2f sec", durationInSecs.count());
+ snprintf(realBuf, sizeof(realBuf), "%6.2f sec", durationInSecs.count());
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"\nTotal Test time (real) = " << realBuf << "\n",
this->Quiet);
@@ -782,7 +767,7 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
label.resize(maxlen + 3, ' ');
char buf[1024];
- sprintf(buf, "%6.2f sec*proc", labelTimes[i]);
+ snprintf(buf, sizeof(buf), "%6.2f sec*proc", labelTimes[i]);
std::ostringstream labelCountStr;
labelCountStr << "(" << labelCounts[i] << " test";
@@ -2181,7 +2166,7 @@ bool cmCTestTestHandler::SetTestsProperties(
// Ensure we have complete triples otherwise the data is corrupt.
if (triples.size() % 3 == 0) {
cmState state(cmState::Unknown);
- rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot());
+ rt.Backtrace = cmListFileBacktrace();
// the first entry represents the top of the trace so we need to
// reconstruct the backtrace in reverse
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 3ac05e7..135e764 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <chrono>
+#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <map>
@@ -13,8 +14,6 @@
#include <utility>
#include <vector>
-#include <stddef.h>
-
#include "cmsys/RegularExpression.hxx"
#include "cmCTest.h"
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index 423b506..d5711c5 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -123,9 +123,10 @@ 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);
- return std::string(current_time);
+ snprintf(current_time, sizeof(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 { current_time };
}
void cmCTestVC::Cleanup()
diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h
index 9bd7229..7b03d10 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -95,15 +95,10 @@ protected:
/** Represent change to one file. */
struct File
{
- PathStatus Status;
- Revision const* Rev;
- Revision const* PriorRev;
- File()
- : Status(PathUpdated)
- , Rev(nullptr)
- , PriorRev(nullptr)
- {
- }
+ PathStatus Status = PathUpdated;
+ Revision const* Rev = nullptr;
+ Revision const* PriorRev = nullptr;
+ File() = default;
File(PathStatus status, Revision const* rev, Revision const* priorRev)
: Status(status)
, Rev(rev)
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 16bca01..e14a4e1 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -511,7 +511,7 @@ std::string cmProcess::GetExitExceptionString() const
default:
char buf[1024];
const char* fmt = "Exit code 0x%" KWIML_INT_PRIx64 "\n";
- _snprintf(buf, 1024, fmt, this->ExitValue);
+ snprintf(buf, sizeof(buf), fmt, this->ExitValue);
exception_str.assign(buf);
}
#else
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index a44aeb0..be030e4 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -5,14 +5,14 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <chrono>
+#include <cstddef>
+#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <cm3p/uv.h>
-#include <stddef.h>
-#include <stdint.h>
#include "cmDuration.h"
#include "cmProcessOutput.h"
@@ -52,9 +52,9 @@ public:
};
State GetProcessStatus();
- int GetId() { return this->Id; }
+ int GetId() const { return this->Id; }
void SetId(int id) { this->Id = id; }
- int64_t GetExitValue() { return this->ExitValue; }
+ int64_t GetExitValue() const { return this->ExitValue; }
cmDuration GetTotalTime() { return this->TotalTime; }
enum class Exception
@@ -111,15 +111,11 @@ private:
class Buffer : public std::vector<char>
{
// Half-open index range of partial line already scanned.
- size_type First;
- size_type Last;
+ size_type First = 0;
+ size_type Last = 0;
public:
- Buffer()
- : First(0)
- , Last(0)
- {
- }
+ Buffer() = default;
bool GetLine(std::string& line);
bool GetLast(std::string& line);
};
diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake
index 2263be3..f59688d 100644
--- a/Source/Checks/cm_c11_thread_local.cmake
+++ b/Source/Checks/cm_c11_thread_local.cmake
@@ -1,5 +1,5 @@
set(CMake_C11_THREAD_LOCAL_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION)
+if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC") AND CMAKE_C11_STANDARD_COMPILE_OPTION)
if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS)
include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake)
cm_message_checks_compat(
diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake
index e5656bf..abf232a 100644
--- a/Source/Checks/cm_cxx14_check.cmake
+++ b/Source/Checks/cm_cxx14_check.cmake
@@ -1,5 +1,5 @@
set(CMake_CXX14_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang|PGI|Intel")
if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
set(CMake_CXX14_WORKS 0)
endif()
diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake
index dba3eaf..78a2382 100644
--- a/Source/Checks/cm_cxx17_check.cmake
+++ b/Source/Checks/cm_cxx17_check.cmake
@@ -1,5 +1,5 @@
set(CMake_CXX17_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang|PGI|Intel")
if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION)
set(CMake_CXX17_WORKS 0)
endif()
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 1ba45e5..1f7776c 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -9,8 +9,6 @@
#include <string>
#include <vector>
-#include <unistd.h>
-
#include "cmsys/Encoding.hxx"
#include "cmCursesColor.h"
@@ -53,31 +51,18 @@ static const char* cmDocumentationOptions[][2] = {
cmCursesForm* cmCursesForm::CurrentForm = nullptr;
+#ifndef _WIN32
extern "C" {
-void onsig(int /*unused*/)
+static void onsig(int /*unused*/)
{
if (cmCursesForm::CurrentForm) {
- endwin();
- if (initscr() == nullptr) {
- static const char errmsg[] = "Error: ncurses initialization failed\n";
- auto r = write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1);
- static_cast<void>(r);
- exit(1);
- }
- noecho(); /* Echo off */
- cbreak(); /* nl- or cr not needed */
- keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
- refresh();
- int x;
- int y;
- getmaxyx(stdscr, y, x);
- cmCursesForm::CurrentForm->Render(1, 1, x, y);
- cmCursesForm::CurrentForm->UpdateStatusBar();
+ cmCursesForm::CurrentForm->HandleResize();
}
signal(SIGWINCH, onsig);
}
}
+#endif // _WIN32
int main(int argc, char const* const* argv)
{
@@ -143,7 +128,9 @@ int main(int argc, char const* const* argv)
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
cmCursesColor::InitColors();
+#ifndef _WIN32
signal(SIGWINCH, onsig);
+#endif // _WIN32
int x;
int y;
diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx
index bd65c4a..ef36b45 100644
--- a/Source/CursesDialog/cmCursesForm.cxx
+++ b/Source/CursesDialog/cmCursesForm.cxx
@@ -2,6 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesForm.h"
+#include <cstdlib>
+#ifndef _WIN32
+# include <unistd.h>
+#endif // _WIN32
+
cmsys::ofstream cmCursesForm::DebugFile;
bool cmCursesForm::Debug = false;
@@ -43,3 +48,27 @@ void cmCursesForm::LogMessage(const char* msg)
cmCursesForm::DebugFile << msg << std::endl;
}
+
+void cmCursesForm::HandleResize()
+{
+ endwin();
+ if (initscr() == nullptr) {
+ static const char errmsg[] = "Error: ncurses initialization failed\n";
+#ifdef _WIN32
+ fprintf(stderr, "%s", errmsg);
+#else
+ auto r = write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1);
+ static_cast<void>(r);
+#endif // _WIN32
+ exit(1);
+ }
+ noecho(); /* Echo off */
+ cbreak(); /* nl- or cr not needed */
+ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
+ refresh();
+ int x;
+ int y;
+ getmaxyx(stdscr, y, x);
+ this->Render(1, 1, x, y);
+ this->UpdateStatusBar();
+}
diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h
index 93459b9..3a1eb25 100644
--- a/Source/CursesDialog/cmCursesForm.h
+++ b/Source/CursesDialog/cmCursesForm.h
@@ -55,6 +55,10 @@ public:
static cmCursesForm* CurrentForm;
+ // Description:
+ // Handle resizing the form with curses.
+ void HandleResize();
+
protected:
static cmsys::ofstream DebugFile;
static bool Debug;
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index 591c546..9b3a649 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -78,7 +78,8 @@ void cmCursesLongMessageForm::UpdateStatusBar()
char version[cmCursesMainForm::MAX_WIDTH];
char vertmp[128];
- sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
+ snprintf(vertmp, sizeof(vertmp), "CMake Version %s",
+ cmVersion::GetCMakeVersion());
size_t sideSpace = (width - strlen(vertmp));
for (size_t i = 0; i < sideSpace; i++) {
version[i] = ' ';
@@ -105,7 +106,7 @@ void cmCursesLongMessageForm::PrintKeys()
return;
}
char firstLine[512];
- sprintf(firstLine, "Press [e] to exit screen");
+ snprintf(firstLine, sizeof(firstLine), "Press [e] to exit screen");
char fmt_s[] = "%s";
curses_move(y - 2, 0);
@@ -176,7 +177,14 @@ void cmCursesLongMessageForm::HandleInput()
this->PrintKeys();
int key = getch();
- sprintf(debugMessage, "Message widget handling input, key: %d", key);
+#ifdef _WIN32
+ if (key == KEY_RESIZE) {
+ HandleResize();
+ }
+#endif // _WIN32
+
+ snprintf(debugMessage, sizeof(debugMessage),
+ "Message widget handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
// quit
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index b28c5b7..11b3b35 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -322,22 +322,22 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
memset(thirdLine, ' ', 68);
} else {
if (this->OkToGenerate) {
- sprintf(firstLine,
- " [l] Show log output [c] Configure"
- " [g] Generate ");
+ snprintf(firstLine, sizeof(firstLine),
+ " [l] Show log output [c] Configure"
+ " [g] Generate ");
} else {
- sprintf(firstLine,
- " [l] Show log output [c] Configure"
- " ");
+ snprintf(firstLine, sizeof(firstLine),
+ " [l] Show log output [c] Configure"
+ " ");
}
{
const char* toggleKeyInstruction =
" [t] Toggle advanced mode (currently %s)";
- sprintf(thirdLine, toggleKeyInstruction,
- this->AdvancedMode ? "on" : "off");
+ snprintf(thirdLine, sizeof(thirdLine), toggleKeyInstruction,
+ this->AdvancedMode ? "on" : "off");
}
- sprintf(secondLine,
- " [h] Help [q] Quit without generating");
+ snprintf(secondLine, sizeof(secondLine),
+ " [h] Help [q] Quit without generating");
}
curses_move(y - 4, 0);
@@ -356,7 +356,8 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
if (cw) {
char pageLine[512] = "";
- sprintf(pageLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages);
+ snprintf(pageLine, sizeof(pageLine), "Page %d of %d", cw->GetPage(),
+ this->NumberOfPages);
curses_move(0, 65 - static_cast<unsigned int>(strlen(pageLine)) - 1);
printw(fmt_s, pageLine);
}
@@ -685,6 +686,12 @@ void cmCursesMainForm::HandleInput()
}
int key = getch();
+#ifdef _WIN32
+ if (key == KEY_RESIZE) {
+ HandleResize();
+ }
+#endif // _WIN32
+
getmaxyx(stdscr, y, x);
// If window too small, handle 'q' only
if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
@@ -739,7 +746,8 @@ void cmCursesMainForm::HandleInput()
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);
+ snprintf(debugMessage, sizeof(debugMessage),
+ "Main form handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
// quit
if (key == 'q') {
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index 4830d63..c0d06ce 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -85,7 +85,8 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
// <Enter> is used to change edit mode (like <Esc> in vi).
while (!this->Done) {
- sprintf(debugMessage, "String widget handling input, key: %d", key);
+ snprintf(debugMessage, sizeof(debugMessage),
+ "String widget handling input, key: %d", key);
cmCursesForm::LogMessage(debugMessage);
fm->PrintKeys();
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 9202bc1..68d28c8 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -5,7 +5,7 @@ project(CMAKE_FORM)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
+ "^(GNU|LCC|Clang|AppleClang|IBMClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Source/CursesDialog/form/fty_enum.c b/Source/CursesDialog/form/fty_enum.c
index 59058a9..f1059b1 100644
--- a/Source/CursesDialog/form/fty_enum.c
+++ b/Source/CursesDialog/form/fty_enum.c
@@ -116,7 +116,7 @@ static int Compare(const unsigned char *s, const unsigned char *buf,
if (*buf=='\0')
{
- return (((*s)!='\0') ? NOMATCH : EXACT);
+ return (((*s)=='\0') ? EXACT : NOMATCH);
}
else
{
@@ -144,7 +144,7 @@ static int Compare(const unsigned char *s, const unsigned char *buf,
/* If it happens that the reference buffer is at its end, the partial
match is actually an exact match. */
- return ((s[-1]!='\0') ? PARTIAL : EXACT);
+ return ((s[-1]=='\0') ? EXACT : PARTIAL);
}
/*---------------------------------------------------------------------------
diff --git a/Source/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx
index 194ae0c..e588853 100644
--- a/Source/LexerParser/cmGccDepfileLexer.cxx
+++ b/Source/LexerParser/cmGccDepfileLexer.cxx
@@ -256,6 +256,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -420,7 +421,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
- int yy_n_chars;
+ yy_size_t 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
@@ -497,7 +498,7 @@ static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
@@ -544,12 +545,12 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (int) (yy_cp - yy_bp); \
+ yyleng = (yy_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 11
-#define YY_END_OF_BUFFER 12
+#define YY_NUM_RULES 12
+#define YY_END_OF_BUFFER 13
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -557,11 +558,11 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[26] =
+static const flex_int16_t yy_accept[31] =
{ 0,
- 0, 0, 12, 10, 8, 6, 10, 9, 10, 10,
- 10, 8, 0, 6, 9, 1, 7, 5, 0, 3,
- 2, 0, 4, 0, 0
+ 0, 0, 13, 11, 9, 6, 11, 10, 11, 11,
+ 11, 9, 0, 6, 10, 1, 8, 7, 0, 0,
+ 5, 0, 3, 2, 0, 8, 0, 4, 0, 0
} ;
static const YY_CHAR yy_ec[256] =
@@ -601,36 +602,40 @@ static const YY_CHAR yy_meta[11] =
1, 2, 1, 1, 2, 1, 1, 1, 1, 3
} ;
-static const flex_int16_t yy_base[28] =
+static const flex_int16_t yy_base[33] =
{ 0,
- 0, 0, 29, 35, 18, 35, 22, 18, 15, 0,
- 8, 12, 16, 35, 11, 35, 0, 35, 13, 35,
- 35, 16, 35, 22, 35, 31, 12
+ 0, 0, 36, 46, 25, 46, 31, 27, 18, 9,
+ 17, 15, 25, 46, 17, 46, 0, 46, 15, 27,
+ 46, 14, 46, 46, 27, 46, 13, 46, 33, 46,
+ 42, 13
} ;
-static const flex_int16_t yy_def[28] =
+static const flex_int16_t yy_def[33] =
{ 0,
- 25, 1, 25, 25, 26, 25, 25, 25, 25, 27,
- 25, 26, 25, 25, 25, 25, 27, 25, 25, 25,
- 25, 25, 25, 25, 0, 25, 25
+ 30, 1, 30, 30, 31, 30, 30, 30, 30, 30,
+ 30, 31, 30, 30, 30, 30, 32, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 0,
+ 30, 30
} ;
-static const flex_int16_t yy_nxt[46] =
+static const flex_int16_t yy_nxt[57] =
{ 0,
4, 5, 6, 7, 5, 8, 4, 9, 10, 11,
- 18, 19, 20, 17, 21, 18, 15, 22, 18, 19,
- 23, 13, 16, 15, 14, 24, 20, 13, 25, 25,
- 25, 22, 12, 12, 3, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25
+ 17, 18, 19, 17, 17, 26, 21, 18, 20, 21,
+ 22, 23, 15, 24, 13, 16, 25, 21, 22, 26,
+ 27, 28, 15, 14, 13, 30, 29, 23, 30, 30,
+ 30, 30, 25, 12, 12, 3, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30
} ;
-static const flex_int16_t yy_chk[46] =
+static const flex_int16_t yy_chk[57] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 11, 11, 11, 27, 11, 19, 15, 11, 13, 13,
- 22, 12, 9, 8, 7, 22, 24, 5, 3, 0,
- 0, 24, 26, 26, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25
+ 10, 10, 10, 10, 32, 27, 22, 19, 10, 11,
+ 11, 11, 15, 11, 12, 9, 11, 13, 13, 20,
+ 20, 25, 8, 7, 5, 3, 25, 29, 0, 0,
+ 0, 0, 29, 31, 31, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30
} ;
/* The intent behind this definition is that it'll catch
@@ -669,8 +674,8 @@ struct yyguts_t
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;
+ yy_size_t yy_n_chars;
+ yy_size_t yyleng_r;
char *yy_c_buf_p;
int yy_init;
int yy_start;
@@ -717,7 +722,7 @@ FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int yyget_leng ( yyscan_t yyscanner );
+ yy_size_t yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
@@ -790,7 +795,7 @@ static int input ( yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- int n; \
+ yy_size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -926,13 +931,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 26 )
+ if ( yy_current_state >= 31 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 35 );
+ while ( yy_base[yy_current_state] != 46 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1006,34 +1011,46 @@ YY_RULE_SETUP
}
YY_BREAK
case 7:
+/* rule 7 can match eol */
YY_RULE_SETUP
{
- // A colon followed by space ends the rules and starts a new dependency.
+ // A colon ends the rules
yyextra->newDependency();
+ // A newline after colon terminates current rule.
+ yyextra->newEntry();
}
YY_BREAK
case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+{
+ // A colon followed by space or line continuation ends the rules
+ // and starts a new dependency.
+ yyextra->newDependency();
+ }
+ YY_BREAK
+case 9:
YY_RULE_SETUP
{
// Rules and dependencies are separated by blocks of whitespace.
yyextra->newRuleOrDependency();
}
YY_BREAK
-case 9:
+case 10:
YY_RULE_SETUP
{
// Got a span of plain text.
yyextra->addToCurrentPath(yytext);
}
YY_BREAK
-case 10:
+case 11:
YY_RULE_SETUP
{
// Got an otherwise unmatched character.
yyextra->addToCurrentPath(yytext);
}
YY_BREAK
-case 11:
+case 12:
YY_RULE_SETUP
ECHO;
YY_BREAK
@@ -1224,7 +1241,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
- int num_to_read =
+ yy_size_t num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1238,7 +1255,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( b->yy_is_our_buffer )
{
- int new_size = b->yy_buf_size * 2;
+ yy_size_t new_size = b->yy_buf_size * 2;
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
@@ -1296,7 +1313,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
- int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -1335,7 +1352,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 26 )
+ if ( yy_current_state >= 31 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1364,11 +1381,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 26 )
+ if ( yy_current_state >= 31 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 25);
+ yy_is_jam = (yy_current_state == 30);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -1389,7 +1406,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
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;
+ yy_size_t 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 =
@@ -1441,7 +1458,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
+ yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1819,12 +1836,12 @@ YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- int i;
+ yy_size_t i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = (yy_size_t) (_yybytes_len + 2);
@@ -1868,7 +1885,7 @@ static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
do \
{ \
/* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
+ yy_size_t 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; \
@@ -1936,7 +1953,7 @@ FILE *yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int yyget_leng (yyscan_t yyscanner)
+yy_size_t yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
diff --git a/Source/LexerParser/cmGccDepfileLexer.h b/Source/LexerParser/cmGccDepfileLexer.h
index 7d34060..ab73ebc 100644
--- a/Source/LexerParser/cmGccDepfileLexer.h
+++ b/Source/LexerParser/cmGccDepfileLexer.h
@@ -258,6 +258,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -371,7 +372,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
- int yy_n_chars;
+ yy_size_t 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
@@ -415,7 +416,7 @@ void yypop_buffer_state ( yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
@@ -462,7 +463,7 @@ FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int yyget_leng ( yyscan_t yyscanner );
+ yy_size_t yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l
index aa2351e..6336b5f 100644
--- a/Source/LexerParser/cmGccDepfileLexer.in.l
+++ b/Source/LexerParser/cmGccDepfileLexer.in.l
@@ -48,8 +48,15 @@ NEWLINE \r?\n
// A newline ends the current file name and the current rule.
yyextra->newEntry();
}
-:{WSPACE}+ {
- // A colon followed by space ends the rules and starts a new dependency.
+:{NEWLINE} {
+ // A colon ends the rules
+ yyextra->newDependency();
+ // A newline after colon terminates current rule.
+ yyextra->newEntry();
+ }
+:({WSPACE}+|\\{NEWLINE}) {
+ // A colon followed by space or line continuation ends the rules
+ // and starts a new dependency.
yyextra->newDependency();
}
{WSPACE}+ {
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 1785571..f90b781 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -730,12 +730,12 @@ void CMakeSetupDialog::updatePreset(const QString& name)
}
void CMakeSetupDialog::showPresetLoadError(
- const QString& dir, cmCMakePresetsFile::ReadFileResult result)
+ const QString& dir, cmCMakePresetsGraph::ReadFileResult result)
{
QMessageBox::warning(
this, "Error Reading CMake Presets",
QString::fromLocal8Bit("Could not read presets from %1: %2")
- .arg(dir, cmCMakePresetsFile::ResultToString(result)));
+ .arg(dir, cmCMakePresetsGraph::ResultToString(result)));
}
void CMakeSetupDialog::doBinaryBrowse()
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index f0cc929..8aee70d 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -60,7 +60,7 @@ protected slots:
void updatePresets(const QVector<QCMakePreset>& presets);
void updatePreset(const QString& name);
void showPresetLoadError(const QString& dir,
- cmCMakePresetsFile::ReadFileResult result);
+ cmCMakePresetsGraph::ReadFileResult result);
void showProgress(const QString& msg, float percent);
void setEnabledState(bool);
bool setupFirstConfigure();
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 8ab8656..ffb6157 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -32,7 +32,7 @@ QCMake::QCMake(QObject* p)
qRegisterMetaType<QCMakePropertyList>();
qRegisterMetaType<QProcessEnvironment>();
qRegisterMetaType<QVector<QCMakePreset>>();
- qRegisterMetaType<cmCMakePresetsFile::ReadFileResult>();
+ qRegisterMetaType<cmCMakePresetsGraph::ReadFileResult>();
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
@@ -69,9 +69,9 @@ QCMake::QCMake(QObject* p)
connect(&this->LoadPresetsTimer, &QTimer::timeout, this, [this]() {
this->loadPresets();
if (!this->PresetName.isEmpty() &&
- this->CMakePresetsFile.ConfigurePresets.find(
+ this->CMakePresetsGraph.ConfigurePresets.find(
std::string(this->PresetName.toLocal8Bit())) ==
- this->CMakePresetsFile.ConfigurePresets.end()) {
+ this->CMakePresetsGraph.ConfigurePresets.end()) {
this->setPreset(QString{});
}
});
@@ -159,7 +159,7 @@ void QCMake::setPreset(const QString& name, bool setBinary)
if (!name.isNull()) {
std::string presetName(name.toLocal8Bit());
auto const& expandedPreset =
- this->CMakePresetsFile.ConfigurePresets[presetName].Expanded;
+ this->CMakePresetsGraph.ConfigurePresets[presetName].Expanded;
if (expandedPreset) {
if (setBinary && !expandedPreset->BinaryDir.empty()) {
QString binaryDir =
@@ -427,7 +427,7 @@ QCMakePropertyList QCMake::properties() const
if (!this->PresetName.isNull()) {
std::string presetName(this->PresetName.toLocal8Bit());
auto const& p =
- this->CMakePresetsFile.ConfigurePresets.at(presetName).Expanded;
+ this->CMakePresetsGraph.ConfigurePresets.at(presetName).Expanded;
if (p) {
for (auto const& v : p->CacheVariables) {
if (!v.second) {
@@ -533,17 +533,17 @@ void QCMake::setUpEnvironment() const
void QCMake::loadPresets()
{
- auto result = this->CMakePresetsFile.ReadProjectPresets(
+ auto result = this->CMakePresetsGraph.ReadProjectPresets(
this->SourceDirectory.toLocal8Bit().data(), true);
if (result != this->LastLoadPresetsResult &&
- result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
emit this->presetLoadError(this->SourceDirectory, result);
}
this->LastLoadPresetsResult = result;
QVector<QCMakePreset> presets;
- for (auto const& name : this->CMakePresetsFile.ConfigurePresetOrder) {
- auto const& it = this->CMakePresetsFile.ConfigurePresets[name];
+ for (auto const& name : this->CMakePresetsGraph.ConfigurePresetOrder) {
+ auto const& it = this->CMakePresetsGraph.ConfigurePresets[name];
auto const& p = it.Unexpanded;
if (p.Hidden) {
continue;
@@ -556,10 +556,10 @@ void QCMake::loadPresets()
preset.generator = QString::fromLocal8Bit(p.Generator.data());
preset.architecture = QString::fromLocal8Bit(p.Architecture.data());
preset.setArchitecture = !p.ArchitectureStrategy ||
- p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
+ p.ArchitectureStrategy == cmCMakePresetsGraph::ArchToolsetStrategy::Set;
preset.toolset = QString::fromLocal8Bit(p.Toolset.data());
preset.setToolset = !p.ToolsetStrategy ||
- p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
+ p.ToolsetStrategy == cmCMakePresetsGraph::ArchToolsetStrategy::Set;
preset.enabled = it.Expanded && it.Expanded->ConditionResult &&
std::find_if(this->AvailableGenerators.begin(),
this->AvailableGenerators.end(),
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index a6751b0..8a7e4cb 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -4,7 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsGraph.h"
#include "cmake.h"
#ifdef _MSC_VER
@@ -60,7 +60,7 @@ using QCMakePropertyList = QList<QCMakeProperty>;
Q_DECLARE_METATYPE(QCMakeProperty)
Q_DECLARE_METATYPE(QCMakePropertyList)
Q_DECLARE_METATYPE(QProcessEnvironment)
-Q_DECLARE_METATYPE(cmCMakePresetsFile::ReadFileResult)
+Q_DECLARE_METATYPE(cmCMakePresetsGraph::ReadFileResult)
/// Qt API for CMake library.
/// Wrapper like class allows for easier integration with
@@ -159,7 +159,7 @@ signals:
void presetChanged(const QString& name);
/// signal when there's an error reading the presets files
void presetLoadError(const QString& dir,
- cmCMakePresetsFile::ReadFileResult error);
+ cmCMakePresetsGraph::ReadFileResult error);
/// signal when uninitialized warning changes
void warnUninitializedModeChanged(bool value);
/// signal for progress events
@@ -202,9 +202,9 @@ protected:
QString Platform;
QString Toolset;
std::vector<cmake::GeneratorInfo> AvailableGenerators;
- cmCMakePresetsFile CMakePresetsFile;
- cmCMakePresetsFile::ReadFileResult LastLoadPresetsResult =
- cmCMakePresetsFile::ReadFileResult::READ_OK;
+ cmCMakePresetsGraph CMakePresetsGraph;
+ cmCMakePresetsGraph::ReadFileResult LastLoadPresetsResult =
+ cmCMakePresetsGraph::ReadFileResult::READ_OK;
QString PresetName;
QString CMakeExecutable;
QAtomicInt InterruptFlag;
diff --git a/Source/QtDialog/QCMakePreset.h b/Source/QtDialog/QCMakePreset.h
index 1609fcb..7387655 100644
--- a/Source/QtDialog/QCMakePreset.h
+++ b/Source/QtDialog/QCMakePreset.h
@@ -5,7 +5,7 @@
#include <QString>
#include <QVariant>
-#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsGraph.h"
class QCMakePreset
{
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index 0dc954a..017fdc0 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -320,9 +320,9 @@ private:
};
#endif
-bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
- std::set<std::string>& symbols,
- std::set<std::string>& dataSymbols)
+static bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
+ std::set<std::string>& dataSymbols)
{
std::string output;
// break up command line into a vector
@@ -375,9 +375,9 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
return true;
}
-bool DumpFile(std::string const& nmPath, const char* filename,
- std::set<std::string>& symbols,
- std::set<std::string>& dataSymbols)
+static bool DumpFile(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
+ std::set<std::string>& dataSymbols)
{
#ifndef _WIN32
return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols);
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
index bd1398f..c5d81c7 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -4,11 +4,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstdio>
#include <set>
#include <string>
-#include <stdio.h>
-
class bindexplib
{
public:
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index a7ce3a6..831e9c7 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -4,6 +4,9 @@
#include <sstream>
#include <unordered_set>
+#include <utility>
+
+#include <cm/memory>
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
@@ -316,21 +319,26 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
}
// Choose which mode of the command to use.
- bool escapeOldStyle = !verbatim;
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetByproducts(byproducts);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment(comment);
+ cc->SetWorkingDirectory(working.c_str());
+ cc->SetEscapeOldStyle(!verbatim);
+ cc->SetUsesTerminal(uses_terminal);
+ cc->SetDepfile(depfile);
+ cc->SetJobPool(job_pool);
+ cc->SetCommandExpandLists(command_expand_lists);
if (source.empty() && output.empty()) {
// Source is empty, use the target.
- std::vector<std::string> no_depends;
- mf.AddCustomCommandToTarget(
- target, byproducts, no_depends, commandLines, cctype, comment,
- working.c_str(), mf.GetPolicyStatus(cmPolicies::CMP0116), escapeOldStyle,
- uses_terminal, depfile, job_pool, command_expand_lists);
+ mf.AddCustomCommandToTarget(target, cctype, std::move(cc));
} else if (target.empty()) {
// Target is empty, use the output.
- mf.AddCustomCommandToOutput(
- output, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, working.c_str(),
- mf.GetPolicyStatus(cmPolicies::CMP0116), nullptr, false, escapeOldStyle,
- uses_terminal, command_expand_lists, depfile, job_pool);
+ cc->SetOutputs(output);
+ cc->SetMainDependency(main_dependency);
+ cc->SetDepends(depends);
+ cc->SetImplicitDepends(implicit_depends);
+ mf.AddCustomCommandToOutput(std::move(cc));
} else if (!byproducts.empty()) {
status.SetError("BYPRODUCTS may not be specified with SOURCE signatures");
return false;
@@ -366,8 +374,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
// Use the old-style mode for backward compatibility.
mf.AddCustomCommandOldStyle(target, outputs, depends, source, commandLines,
- comment,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
+ comment);
}
return true;
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 2b19aad..a246d06 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -4,13 +4,15 @@
#include <utility>
+#include <cm/memory>
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -211,11 +213,18 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
}
// Add the utility target to the makefile.
- bool escapeOldStyle = !verbatim;
- cmTarget* target = mf.AddUtilityCommand(
- targetName, excludeFromAll, working_directory.c_str(), byproducts, depends,
- commandLines, mf.GetPolicyStatus(cmPolicies::CMP0116), escapeOldStyle,
- comment, uses_terminal, command_expand_lists, job_pool);
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetWorkingDirectory(working_directory.c_str());
+ cc->SetByproducts(byproducts);
+ cc->SetDepends(depends);
+ cc->SetCommandLines(commandLines);
+ cc->SetEscapeOldStyle(!verbatim);
+ cc->SetComment(comment);
+ cc->SetUsesTerminal(uses_terminal);
+ cc->SetCommandExpandLists(command_expand_lists);
+ cc->SetJobPool(job_pool);
+ cmTarget* target =
+ mf.AddUtilityCommand(targetName, excludeFromAll, std::move(cc));
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx
index 35443e7..591199b 100644
--- a/Source/cmAffinity.cxx
+++ b/Source/cmAffinity.cxx
@@ -12,7 +12,7 @@
# define CM_HAVE_CPU_AFFINITY
# include <pthread.h>
# include <sched.h>
-// On some platforms CPU_ZERO needs memset but sched.h forgets string.h
+// On some platforms CPU_ZERO needs memset but sched.h forgets cstring
# include <cstring> // IWYU pragma: keep
# if defined(__FreeBSD__)
# include <pthread_np.h>
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
index a9c15c2..e8e46aa 100644
--- a/Source/cmBase32.cxx
+++ b/Source/cmBase32.cxx
@@ -12,7 +12,7 @@ inline unsigned char Base32EncodeChar(int schar)
return Base32EncodeTable[schar];
}
-void Base32Encode5(const unsigned char src[5], char dst[8])
+static void Base32Encode5(const unsigned char src[5], char dst[8])
{
// [0]:5 bits
dst[0] = Base32EncodeChar((src[0] >> 3) & 0x1F);
diff --git a/Source/cmBuildOptions.h b/Source/cmBuildOptions.h
new file mode 100644
index 0000000..aa3184e
--- /dev/null
+++ b/Source/cmBuildOptions.h
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+/** \brief Defines how to resolve packages **/
+enum class PackageResolveMode
+{
+ /** \brief Behavior is defined by preset or cache variable (e.g.
+ CMAKE_VS_NUGET_PACKAGE_RESTORE). This is the default. **/
+ Default,
+
+ /** \brief Ignore behavior defined by preset or cache variable and forces
+ packages to be resolved prior to build. **/
+ Force,
+
+ /** \brief Ignore behavior defined by preset or cache variable and forces
+ packages to be resolved, but skip the actual build. **/
+ OnlyResolve,
+
+ /** \brief Ignore behavior defined by preset or cache variable and don't
+ resolve any packages **/
+ Disable
+};
+
+struct cmBuildOptions
+{
+public:
+ cmBuildOptions() noexcept = default;
+ explicit cmBuildOptions(bool clean, bool fast,
+ PackageResolveMode resolveMode) noexcept
+ : Clean(clean)
+ , Fast(fast)
+ , ResolveMode(resolveMode)
+ {
+ }
+ explicit cmBuildOptions(const cmBuildOptions&) noexcept = default;
+ cmBuildOptions& operator=(const cmBuildOptions&) noexcept = default;
+
+ bool Clean = false;
+ bool Fast = false;
+ PackageResolveMode ResolveMode = PackageResolveMode::Default;
+};
diff --git a/Source/cmCMakePresetsFileInternal.h b/Source/cmCMakePresetsFileInternal.h
deleted file mode 100644
index 3269276..0000000
--- a/Source/cmCMakePresetsFileInternal.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include <memory>
-
-#include "cmCMakePresetsFile.h"
-
-#define CHECK_OK(expr) \
- { \
- auto _result = expr; \
- if (_result != ReadFileResult::READ_OK) \
- return _result; \
- }
-
-namespace cmCMakePresetsFileInternal {
-enum class ExpandMacroResult
-{
- Ok,
- Ignore,
- Error,
-};
-
-using MacroExpander = std::function<ExpandMacroResult(
- const std::string&, const std::string&, std::string&, int version)>;
-}
-
-class cmCMakePresetsFile::Condition
-{
-public:
- virtual ~Condition() = default;
-
- virtual bool Evaluate(
- const std::vector<cmCMakePresetsFileInternal::MacroExpander>& expanders,
- int version, cm::optional<bool>& out) const = 0;
- virtual bool IsNull() const { return false; }
-};
-
-namespace cmCMakePresetsFileInternal {
-
-class NullCondition : public cmCMakePresetsFile::Condition
-{
- bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
- int /*version*/, cm::optional<bool>& out) const override
- {
- out = true;
- return true;
- }
-
- bool IsNull() const override { return true; }
-};
-
-class ConstCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
- int /*version*/, cm::optional<bool>& out) const override
- {
- out = this->Value;
- return true;
- }
-
- bool Value;
-};
-
-class EqualsCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
- cm::optional<bool>& out) const override;
-
- std::string Lhs;
- std::string Rhs;
-};
-
-class InListCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
- cm::optional<bool>& out) const override;
-
- std::string String;
- std::vector<std::string> List;
-};
-
-class MatchesCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
- cm::optional<bool>& out) const override;
-
- std::string String;
- std::string Regex;
-};
-
-class AnyAllOfCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
- cm::optional<bool>& out) const override;
-
- std::vector<std::unique_ptr<Condition>> Conditions;
- bool StopValue;
-};
-
-class NotCondition : public cmCMakePresetsFile::Condition
-{
-public:
- bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
- cm::optional<bool>& out) const override;
-
- std::unique_ptr<Condition> SubCondition;
-};
-}
diff --git a/Source/cmCMakePresetsFileReadJSON.cxx b/Source/cmCMakePresetsFileReadJSON.cxx
deleted file mode 100644
index 489551d..0000000
--- a/Source/cmCMakePresetsFileReadJSON.cxx
+++ /dev/null
@@ -1,1032 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include <functional>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <cm/memory>
-#include <cm/optional>
-#include <cmext/string_view>
-
-#include <cm3p/json/reader.h>
-#include <cm3p/json/value.h>
-
-#include "cmsys/FStream.hxx"
-
-#include "cmCMakePresetsFile.h"
-#include "cmCMakePresetsFileInternal.h"
-#include "cmJSONHelpers.h"
-#include "cmVersion.h"
-
-namespace {
-using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
-using CacheVariable = cmCMakePresetsFile::CacheVariable;
-using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
-using BuildPreset = cmCMakePresetsFile::BuildPreset;
-using TestPreset = cmCMakePresetsFile::TestPreset;
-using ArchToolsetStrategy = cmCMakePresetsFile::ArchToolsetStrategy;
-
-constexpr int MIN_VERSION = 1;
-constexpr int MAX_VERSION = 3;
-
-struct CMakeVersion
-{
- unsigned int Major = 0;
- unsigned int Minor = 0;
- unsigned int Patch = 0;
-};
-
-struct RootPresets
-{
- CMakeVersion CMakeMinimumRequired;
- std::vector<cmCMakePresetsFile::ConfigurePreset> ConfigurePresets;
- std::vector<cmCMakePresetsFile::BuildPreset> BuildPresets;
- std::vector<cmCMakePresetsFile::TestPreset> TestPresets;
-};
-
-std::unique_ptr<cmCMakePresetsFileInternal::NotCondition> InvertCondition(
- std::unique_ptr<cmCMakePresetsFile::Condition> condition)
-{
- auto retval = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
- retval->SubCondition = std::move(condition);
- return retval;
-}
-
-auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
-
-auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
-
-auto const ConditionStringListHelper =
- cmJSONVectorHelper<std::string, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
- ConditionStringHelper);
-
-auto const ConstConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::ConstCondition,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("value"_s, &cmCMakePresetsFileInternal::ConstCondition::Value,
- ConditionBoolHelper, true);
-
-auto const EqualsConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::EqualsCondition,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("lhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Lhs,
- ConditionStringHelper, true)
- .Bind("rhs"_s, &cmCMakePresetsFileInternal::EqualsCondition::Rhs,
- ConditionStringHelper, true);
-
-auto const InListConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::InListCondition,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("string"_s, &cmCMakePresetsFileInternal::InListCondition::String,
- ConditionStringHelper, true)
- .Bind("list"_s, &cmCMakePresetsFileInternal::InListCondition::List,
- ConditionStringListHelper, true);
-
-auto const MatchesConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::MatchesCondition,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("string"_s, &cmCMakePresetsFileInternal::MatchesCondition::String,
- ConditionStringHelper, true)
- .Bind("regex"_s, &cmCMakePresetsFileInternal::MatchesCondition::Regex,
- ConditionStringHelper, true);
-
-ReadFileResult SubConditionHelper(
- std::unique_ptr<cmCMakePresetsFile::Condition>& out,
- const Json::Value* value);
-
-auto const ListConditionVectorHelper =
- cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsFile::Condition>,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION,
- SubConditionHelper);
-auto const AnyAllOfConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::AnyAllOfCondition,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("conditions"_s,
- &cmCMakePresetsFileInternal::AnyAllOfCondition::Conditions,
- ListConditionVectorHelper);
-
-auto const NotConditionHelper =
- cmJSONObjectHelper<cmCMakePresetsFileInternal::NotCondition, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION, false)
- .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
- .Bind("condition"_s,
- &cmCMakePresetsFileInternal::NotCondition::SubCondition,
- SubConditionHelper);
-
-ReadFileResult ConditionHelper(
- std::unique_ptr<cmCMakePresetsFile::Condition>& out,
- const Json::Value* value)
-{
- if (!value) {
- out.reset();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isBool()) {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
- c->Value = value->asBool();
- out = std::move(c);
- return ReadFileResult::READ_OK;
- }
-
- if (value->isNull()) {
- out = cm::make_unique<cmCMakePresetsFileInternal::NullCondition>();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- if (!value->isMember("type")) {
- return ReadFileResult::INVALID_CONDITION;
- }
-
- if (!(*value)["type"].isString()) {
- return ReadFileResult::INVALID_CONDITION;
- }
- auto type = (*value)["type"].asString();
-
- if (type == "const") {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::ConstCondition>();
- CHECK_OK(ConstConditionHelper(*c, value));
- out = std::move(c);
- return ReadFileResult::READ_OK;
- }
-
- if (type == "equals" || type == "notEquals") {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::EqualsCondition>();
- CHECK_OK(EqualsConditionHelper(*c, value));
- out = std::move(c);
- if (type == "notEquals") {
- out = InvertCondition(std::move(out));
- }
- return ReadFileResult::READ_OK;
- }
-
- if (type == "inList" || type == "notInList") {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::InListCondition>();
- CHECK_OK(InListConditionHelper(*c, value));
- out = std::move(c);
- if (type == "notInList") {
- out = InvertCondition(std::move(out));
- }
- return ReadFileResult::READ_OK;
- }
-
- if (type == "matches" || type == "notMatches") {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::MatchesCondition>();
- CHECK_OK(MatchesConditionHelper(*c, value));
- out = std::move(c);
- if (type == "notMatches") {
- out = InvertCondition(std::move(out));
- }
- return ReadFileResult::READ_OK;
- }
-
- if (type == "anyOf" || type == "allOf") {
- auto c =
- cm::make_unique<cmCMakePresetsFileInternal::AnyAllOfCondition>();
- c->StopValue = (type == "anyOf");
- CHECK_OK(AnyAllOfConditionHelper(*c, value));
- out = std::move(c);
- return ReadFileResult::READ_OK;
- }
-
- if (type == "not") {
- auto c = cm::make_unique<cmCMakePresetsFileInternal::NotCondition>();
- CHECK_OK(NotConditionHelper(*c, value));
- out = std::move(c);
- return ReadFileResult::READ_OK;
- }
- }
-
- return ReadFileResult::INVALID_CONDITION;
-}
-
-ReadFileResult PresetConditionHelper(
- std::shared_ptr<cmCMakePresetsFile::Condition>& out,
- const Json::Value* value)
-{
- std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
- auto result = ConditionHelper(ptr, value);
- out = std::move(ptr);
- return result;
-}
-
-ReadFileResult SubConditionHelper(
- std::unique_ptr<cmCMakePresetsFile::Condition>& out,
- const Json::Value* value)
-{
- std::unique_ptr<cmCMakePresetsFile::Condition> ptr;
- auto result = ConditionHelper(ptr, value);
- if (ptr && ptr->IsNull()) {
- return ReadFileResult::INVALID_CONDITION;
- }
- out = std::move(ptr);
- return result;
-}
-
-cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
-{
- return [error](std::nullptr_t& /*out*/,
- const Json::Value* value) -> ReadFileResult {
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isObject()) {
- return error;
- }
-
- return ReadFileResult::READ_OK;
- };
-}
-
-auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
- ReadFileResult::NO_VERSION, VersionIntHelper);
-
-auto const RootVersionHelper =
- cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_ROOT)
- .Bind("version"_s, VersionHelper, false);
-
-auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
-
-ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
-{
- if (!value) {
- out.clear();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isBool()) {
- out = value->asBool() ? "TRUE" : "FALSE";
- return ReadFileResult::READ_OK;
- }
-
- return VariableStringHelper(out, value);
-}
-
-auto const VariableObjectHelper =
- cmJSONObjectHelper<CacheVariable, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
- .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
- .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
-
-ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
- const Json::Value* value)
-{
- if (value->isBool()) {
- out = CacheVariable{
- /*Type=*/"BOOL",
- /*Value=*/value->asBool() ? "TRUE" : "FALSE",
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = CacheVariable{
- /*Type=*/"",
- /*Value=*/value->asString(),
- };
- return ReadFileResult::READ_OK;
- }
- if (value->isObject()) {
- out.emplace();
- return VariableObjectHelper(*out, value);
- }
- if (value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_VARIABLE;
-}
-
-auto const VariablesHelper =
- cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
-
-auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
- const Json::Value* value)
-{
- if (!value || value->isNull()) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
- if (value->isString()) {
- out = value->asString();
- return ReadFileResult::READ_OK;
- }
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const EnvironmentMapHelper =
- cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- EnvironmentHelper);
-
-auto const PresetVectorStringHelper =
- cmJSONVectorHelper<std::string, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
- PresetStringHelper);
-
-ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
- const Json::Value* value)
-{
- out.clear();
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.push_back(value->asString());
- return ReadFileResult::READ_OK;
- }
-
- return PresetVectorStringHelper(out, value);
-}
-
-auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalBoolHelper =
- cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
- PresetBoolHelper);
-
-auto const PresetIntHelper = cmJSONIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
-
-auto const PresetOptionalIntHelper = cmJSONOptionalHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, PresetIntHelper);
-
-auto const PresetVectorIntHelper = cmJSONVectorHelper<int, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
-
-auto const PresetWarningsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::WarnDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
- PresetOptionalBoolHelper, false)
- .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
- PresetOptionalBoolHelper, false)
- .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
- PresetOptionalBoolHelper, false)
- .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
- PresetOptionalBoolHelper, false);
-
-auto const PresetErrorsHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("dev"_s, &ConfigurePreset::ErrorDev, PresetOptionalBoolHelper, false)
- .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
- PresetOptionalBoolHelper, false);
-
-auto const PresetDebugHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("output"_s, &ConfigurePreset::DebugOutput, PresetOptionalBoolHelper,
- false)
- .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
- PresetOptionalBoolHelper, false)
- .Bind("find"_s, &ConfigurePreset::DebugFind, PresetOptionalBoolHelper,
- false);
-
-ReadFileResult ArchToolsetStrategyHelper(
- cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "set") {
- out = ArchToolsetStrategy::Set;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "external") {
- out = ArchToolsetStrategy::External;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
-ArchToolsetHelper(
- std::string ConfigurePreset::*valueField,
- cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
-{
- auto const objectHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("value", valueField, PresetStringHelper, false)
- .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
- return [valueField, strategyField, objectHelper](
- ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
- if (!value) {
- (out.*valueField).clear();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.*valueField = value->asString();
- out.*strategyField = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return objectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
- };
-}
-
-auto const ArchitectureHelper = ArchToolsetHelper(
- &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
-auto const ToolsetHelper = ArchToolsetHelper(
- &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
-
-auto const ConfigurePresetHelper =
- cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &ConfigurePreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &ConfigurePreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &ConfigurePreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &ConfigurePreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &ConfigurePreset::Description, PresetStringHelper,
- false)
- .Bind("generator"_s, &ConfigurePreset::Generator, PresetStringHelper,
- false)
- .Bind("architecture"_s, ArchitectureHelper, false)
- .Bind("toolset"_s, ToolsetHelper, false)
- .Bind("toolchainFile"_s, &ConfigurePreset::ToolchainFile,
- PresetStringHelper, false)
- .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir, PresetStringHelper,
- false)
- .Bind("installDir"_s, &ConfigurePreset::InstallDir, PresetStringHelper,
- false)
- .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
- .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
- VariablesHelper, false)
- .Bind("environment"_s, &ConfigurePreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("warnings"_s, PresetWarningsHelper, false)
- .Bind("errors"_s, PresetErrorsHelper, false)
- .Bind("debug"_s, PresetDebugHelper, false)
- .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator,
- PresetConditionHelper, false);
-
-auto const BuildPresetHelper =
- cmJSONObjectHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &BuildPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &BuildPreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &BuildPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &BuildPreset::DisplayName, PresetStringHelper,
- false)
- .Bind("description"_s, &BuildPreset::Description, PresetStringHelper,
- false)
- .Bind("environment"_s, &BuildPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &BuildPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("jobs"_s, &BuildPreset::Jobs, PresetOptionalIntHelper, false)
- .Bind("targets"_s, &BuildPreset::Targets,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("configuration"_s, &BuildPreset::Configuration, PresetStringHelper,
- false)
- .Bind("cleanFirst"_s, &BuildPreset::CleanFirst, PresetOptionalBoolHelper,
- false)
- .Bind("verbose"_s, &BuildPreset::Verbose, PresetOptionalBoolHelper, false)
- .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
- PresetVectorStringHelper, false)
- .Bind("condition"_s, &BuildPreset::ConditionEvaluator,
- PresetConditionHelper, false);
-
-ReadFileResult TestPresetOutputVerbosityHelper(
- TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::OutputOptions::VerbosityEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "verbose") {
- out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "extra") {
- out = TestPreset::OutputOptions::VerbosityEnum::Extra;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalOutputVerbosityHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetOutputVerbosityHelper);
-
-auto const TestPresetOptionalOutputHelper =
- cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
- PresetOptionalBoolHelper, false)
- .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
- TestPresetOptionalOutputVerbosityHelper, false)
- .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
- PresetOptionalBoolHelper, false)
- .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
- PresetOptionalBoolHelper, false)
- .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
- PresetStringHelper, false)
- .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
- PresetOptionalBoolHelper, false)
- .Bind("subprojectSummary"_s,
- &TestPreset::OutputOptions::SubprojectSummary,
- PresetOptionalBoolHelper, false)
- .Bind("maxPassedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxPassedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxFailedTestOutputSize"_s,
- &TestPreset::OutputOptions::MaxFailedTestOutputSize,
- PresetOptionalIntHelper, false)
- .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
- PresetOptionalIntHelper, false));
-
-auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
- PresetOptionalIntHelper, false)
- .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
- PresetOptionalIntHelper, false)
- .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
- PresetOptionalIntHelper, false)
- .Bind("specificTests"_s,
- &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
- PresetVectorIntHelper, false));
-
-ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
- cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
- const Json::Value* value)
-{
- if (!value) {
- out = cm::nullopt;
- return ReadFileResult::READ_OK;
- }
-
- if (value->isString()) {
- out.emplace();
- out->IndexFile = value->asString();
- return ReadFileResult::READ_OK;
- }
-
- if (value->isObject()) {
- return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalFilterIncludeHelper =
- cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::IncludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::IncludeOptions::Label, PresetStringHelper,
- false)
- .Bind("index"_s, &TestPreset::IncludeOptions::Index,
- TestPresetOptionalFilterIncludeIndexHelper, false)
- .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
- PresetOptionalBoolHelper, false));
-
-auto const TestPresetOptionalFilterExcludeFixturesHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
- PresetStringHelper, false)
- .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
- PresetStringHelper, false)
- .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
- PresetStringHelper, false));
-
-auto const TestPresetOptionalFilterExcludeHelper =
- cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("name"_s, &TestPreset::ExcludeOptions::Name, PresetStringHelper,
- false)
- .Bind("label"_s, &TestPreset::ExcludeOptions::Label, PresetStringHelper,
- false)
- .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
- TestPresetOptionalFilterExcludeFixturesHelper, false));
-
-ReadFileResult TestPresetExecutionShowOnlyHelper(
- TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
-{
- if (!value || !value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "human") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "json-v1") {
- out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionShowOnlyHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionShowOnlyHelper);
-
-ReadFileResult TestPresetExecutionModeHelper(
- TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "until-fail") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "until-pass") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "after-timeout") {
- out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionRepeatHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
- ReadFileResult>(ReadFileResult::READ_OK,
- ReadFileResult::INVALID_PRESET)
- .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
- TestPresetExecutionModeHelper, true)
- .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
- PresetIntHelper, true));
-
-ReadFileResult TestPresetExecutionNoTestsActionHelper(
- TestPreset::ExecutionOptions::NoTestsActionEnum& out,
- const Json::Value* value)
-{
- if (!value) {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (!value->isString()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- if (value->asString() == "default") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "error") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
- return ReadFileResult::READ_OK;
- }
-
- if (value->asString() == "ignore") {
- out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
- return ReadFileResult::READ_OK;
- }
-
- return ReadFileResult::INVALID_PRESET;
-}
-
-auto const TestPresetOptionalExecutionNoTestsActionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
- ReadFileResult>(ReadFileResult::READ_OK,
- TestPresetExecutionNoTestsActionHelper);
-
-auto const TestPresetExecutionHelper =
- cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
- PresetOptionalBoolHelper, false)
- .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
- PresetOptionalBoolHelper, false)
- .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
- PresetOptionalIntHelper, false)
- .Bind("resourceSpecFile"_s,
- &TestPreset::ExecutionOptions::ResourceSpecFile,
- PresetStringHelper, false)
- .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
- PresetOptionalIntHelper, false)
- .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
- TestPresetOptionalExecutionShowOnlyHelper, false)
- .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
- TestPresetOptionalExecutionRepeatHelper, false)
- .Bind("interactiveDebugging"_s,
- &TestPreset::ExecutionOptions::InteractiveDebugging,
- PresetOptionalBoolHelper, false)
- .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
- PresetOptionalBoolHelper, false)
- .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
- PresetOptionalIntHelper, false)
- .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
- TestPresetOptionalExecutionNoTestsActionHelper, false));
-
-auto const TestPresetFilterHelper =
- cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK,
- cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
- .Bind("include"_s, &TestPreset::FilterOptions::Include,
- TestPresetOptionalFilterIncludeHelper, false)
- .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
- TestPresetOptionalFilterExcludeHelper, false));
-
-auto const TestPresetHelper =
- cmJSONObjectHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
- .Bind("name"_s, &TestPreset::Name, PresetStringHelper)
- .Bind("inherits"_s, &TestPreset::Inherits,
- PresetVectorOneOrMoreStringHelper, false)
- .Bind("hidden"_s, &TestPreset::Hidden, PresetBoolHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_PRESET), false)
- .Bind("displayName"_s, &TestPreset::DisplayName, PresetStringHelper, false)
- .Bind("description"_s, &TestPreset::Description, PresetStringHelper, false)
- .Bind("environment"_s, &TestPreset::Environment, EnvironmentMapHelper,
- false)
- .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
- PresetStringHelper, false)
- .Bind("inheritConfigureEnvironment"_s,
- &TestPreset::InheritConfigureEnvironment, PresetOptionalBoolHelper,
- false)
- .Bind("configuration"_s, &TestPreset::Configuration, PresetStringHelper,
- false)
- .Bind("overwriteConfigurationFile"_s,
- &TestPreset::OverwriteConfigurationFile, PresetVectorStringHelper,
- false)
- .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
- false)
- .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
- .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
- false)
- .Bind("condition"_s, &TestPreset::ConditionEvaluator,
- PresetConditionHelper, false);
-
-auto const ConfigurePresetsHelper =
- cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- ConfigurePresetHelper);
-
-auto const BuildPresetsHelper =
- cmJSONVectorHelper<BuildPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
- BuildPresetHelper);
-
-auto const TestPresetsHelper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, TestPresetHelper);
-
-auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
-
-auto const CMakeVersionHelper =
- cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
- .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
- .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
- .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
-
-auto const RootPresetsHelper =
- cmJSONObjectHelper<RootPresets, ReadFileResult>(
- ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
- .Bind<int>("version"_s, nullptr, VersionHelper)
- .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
- ConfigurePresetsHelper, false)
- .Bind("buildPresets"_s, &RootPresets::BuildPresets, BuildPresetsHelper,
- false)
- .Bind("testPresets"_s, &RootPresets::TestPresets, TestPresetsHelper, false)
- .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
- CMakeVersionHelper, false)
- .Bind<std::nullptr_t>("vendor"_s, nullptr,
- VendorHelper(ReadFileResult::INVALID_ROOT), false);
-}
-
-cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
- const std::string& filename, bool user)
-{
- cmsys::ifstream fin(filename.c_str());
- if (!fin) {
- return ReadFileResult::FILE_NOT_FOUND;
- }
- // If there's a BOM, toss it.
- cmsys::FStream::ReadBOM(fin);
-
- Json::Value root;
- Json::CharReaderBuilder builder;
- Json::CharReaderBuilder::strictMode(&builder.settings_);
- if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
- return ReadFileResult::JSON_PARSE_ERROR;
- }
-
- int v = 0;
- auto result = RootVersionHelper(v, &root);
- if (result != ReadFileResult::READ_OK) {
- return result;
- }
- if (v < MIN_VERSION || v > MAX_VERSION) {
- return ReadFileResult::UNRECOGNIZED_VERSION;
- }
- if (user) {
- this->UserVersion = v;
- } else {
- this->Version = v;
- }
-
- // Support for build and test presets added in version 2.
- if (v < 2 &&
- (root.isMember("buildPresets") || root.isMember("testPresets"))) {
- return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
- }
-
- RootPresets presets;
- if ((result = RootPresetsHelper(presets, &root)) !=
- ReadFileResult::READ_OK) {
- return result;
- }
-
- unsigned int currentMajor = cmVersion::GetMajorVersion();
- unsigned int currentMinor = cmVersion::GetMinorVersion();
- unsigned int currentPatch = cmVersion::GetPatchVersion();
- auto const& required = presets.CMakeMinimumRequired;
- if (required.Major > currentMajor ||
- (required.Major == currentMajor &&
- (required.Minor > currentMinor ||
- (required.Minor == currentMinor &&
- (required.Patch > currentPatch))))) {
- return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
- }
-
- for (auto& preset : presets.ConfigurePresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<ConfigurePreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->ConfigurePresets
- .emplace(std::make_pair(preset.Name, presetPair))
- .second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
-
- // Support for installDir presets added in version 3.
- if (v < 3 && !preset.InstallDir.empty()) {
- return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
- }
-
- // Support for conditions added in version 3.
- if (v < 3 && preset.ConditionEvaluator) {
- return ReadFileResult::CONDITION_UNSUPPORTED;
- }
-
- // Support for toolchainFile presets added in version 3.
- if (v < 3 && !preset.ToolchainFile.empty()) {
- return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
- }
-
- this->ConfigurePresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.BuildPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<BuildPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
-
- // Support for conditions added in version 3.
- if (v < 3 && preset.ConditionEvaluator) {
- return ReadFileResult::CONDITION_UNSUPPORTED;
- }
-
- this->BuildPresetOrder.push_back(preset.Name);
- }
-
- for (auto& preset : presets.TestPresets) {
- preset.User = user;
- if (preset.Name.empty()) {
- return ReadFileResult::INVALID_PRESET;
- }
-
- PresetPair<TestPreset> presetPair;
- presetPair.Unexpanded = preset;
- presetPair.Expanded = cm::nullopt;
- if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
- return ReadFileResult::DUPLICATE_PRESETS;
- }
-
- // Support for conditions added in version 3.
- if (v < 3 && preset.ConditionEvaluator) {
- return ReadFileResult::CONDITION_UNSUPPORTED;
- }
-
- this->TestPresetOrder.push_back(preset.Name);
- }
-
- return ReadFileResult::READ_OK;
-}
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsGraph.cxx
index 538b668..705e2b0 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsGraph.cxx
@@ -1,8 +1,9 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsGraph.h"
#include <algorithm>
+#include <cassert>
#include <cstdlib>
#include <functional>
#include <iostream>
@@ -13,12 +14,12 @@
#include "cmsys/RegularExpression.hxx"
-#include "cmCMakePresetsFileInternal.h"
+#include "cmCMakePresetsGraphInternal.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#define CHECK_EXPAND(out, field, expanders, version) \
- { \
+ do { \
switch (ExpandMacros(field, expanders, version)) { \
case ExpandMacroResult::Error: \
return false; \
@@ -28,7 +29,7 @@
case ExpandMacroResult::Ok: \
break; \
} \
- }
+ } while (false)
namespace {
enum class CycleStatus
@@ -38,12 +39,12 @@ enum class CycleStatus
Verified,
};
-using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
-using ConfigurePreset = cmCMakePresetsFile::ConfigurePreset;
-using BuildPreset = cmCMakePresetsFile::BuildPreset;
-using TestPreset = cmCMakePresetsFile::TestPreset;
-using ExpandMacroResult = cmCMakePresetsFileInternal::ExpandMacroResult;
-using MacroExpander = cmCMakePresetsFileInternal::MacroExpander;
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
+using BuildPreset = cmCMakePresetsGraph::BuildPreset;
+using TestPreset = cmCMakePresetsGraph::TestPreset;
+using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult;
+using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander;
void InheritString(std::string& child, const std::string& parent)
{
@@ -77,9 +78,10 @@ void InheritVector(std::vector<T>& child, const std::vector<T>& parent)
*/
template <class T>
ReadFileResult VisitPreset(
- T& preset, std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
+ T& preset,
+ std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
std::map<std::string, CycleStatus> cycleStatus,
- const cmCMakePresetsFile& file)
+ const cmCMakePresetsGraph& graph)
{
switch (cycleStatus[preset.Name]) {
case CycleStatus::InProgress:
@@ -96,7 +98,7 @@ ReadFileResult VisitPreset(
return ReadFileResult::INVALID_PRESET;
}
- CHECK_OK(preset.VisitPresetBeforeInherit())
+ CHECK_OK(preset.VisitPresetBeforeInherit());
for (auto const& i : preset.Inherits) {
auto parent = presets.find(i);
@@ -105,16 +107,16 @@ ReadFileResult VisitPreset(
}
auto& parentPreset = parent->second.Unexpanded;
- if (!preset.User && parentPreset.User) {
- return ReadFileResult::USER_PRESET_INHERITANCE;
+ if (!preset.OriginFile->ReachableFiles.count(parentPreset.OriginFile)) {
+ return ReadFileResult::INHERITED_PRESET_UNREACHABLE_FROM_FILE;
}
- auto result = VisitPreset(parentPreset, presets, cycleStatus, file);
+ auto result = VisitPreset(parentPreset, presets, cycleStatus, graph);
if (result != ReadFileResult::READ_OK) {
return result;
}
- CHECK_OK(preset.VisitPresetInherit(parentPreset))
+ CHECK_OK(preset.VisitPresetInherit(parentPreset));
for (auto const& v : parentPreset.Environment) {
preset.Environment.insert(v);
@@ -129,7 +131,7 @@ ReadFileResult VisitPreset(
preset.ConditionEvaluator.reset();
}
- CHECK_OK(preset.VisitPresetAfterInherit(file.GetVersion(preset)))
+ CHECK_OK(preset.VisitPresetAfterInherit(graph.GetVersion(preset)));
cycleStatus[preset.Name] = CycleStatus::Verified;
return ReadFileResult::READ_OK;
@@ -137,8 +139,8 @@ ReadFileResult VisitPreset(
template <class T>
ReadFileResult ComputePresetInheritance(
- std::map<std::string, cmCMakePresetsFile::PresetPair<T>>& presets,
- const cmCMakePresetsFile& file)
+ std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets,
+ const cmCMakePresetsGraph& graph)
{
std::map<std::string, CycleStatus> cycleStatus;
for (auto const& it : presets) {
@@ -147,7 +149,7 @@ ReadFileResult ComputePresetInheritance(
for (auto& it : presets) {
auto& preset = it.second.Unexpanded;
- auto result = VisitPreset<T>(preset, presets, cycleStatus, file);
+ auto result = VisitPreset<T>(preset, presets, cycleStatus, graph);
if (result != ReadFileResult::READ_OK) {
return result;
}
@@ -189,17 +191,17 @@ ExpandMacroResult ExpandMacro(std::string& out,
const std::vector<MacroExpander>& macroExpanders,
int version);
-bool ExpandMacros(const cmCMakePresetsFile& file,
+bool ExpandMacros(const cmCMakePresetsGraph& graph,
const ConfigurePreset& preset,
cm::optional<ConfigurePreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
std::string binaryDir = preset.BinaryDir;
- CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset))
+ CHECK_EXPAND(out, binaryDir, macroExpanders, graph.GetVersion(preset));
if (!binaryDir.empty()) {
if (!cmSystemTools::FileIsFullPath(binaryDir)) {
- binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
+ binaryDir = cmStrCat(graph.SourceDir, '/', binaryDir);
}
out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
@@ -207,10 +209,10 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
if (!preset.InstallDir.empty()) {
std::string installDir = preset.InstallDir;
- CHECK_EXPAND(out, installDir, macroExpanders, file.GetVersion(preset))
+ CHECK_EXPAND(out, installDir, macroExpanders, graph.GetVersion(preset));
if (!cmSystemTools::FileIsFullPath(installDir)) {
- installDir = cmStrCat(file.SourceDir, '/', installDir);
+ installDir = cmStrCat(graph.SourceDir, '/', installDir);
}
out->InstallDir = cmSystemTools::CollapseFullPath(installDir);
cmSystemTools::ConvertToUnixSlashes(out->InstallDir);
@@ -218,89 +220,89 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
if (!preset.ToolchainFile.empty()) {
std::string toolchain = preset.ToolchainFile;
- CHECK_EXPAND(out, toolchain, macroExpanders, file.GetVersion(preset))
+ CHECK_EXPAND(out, toolchain, macroExpanders, graph.GetVersion(preset));
out->ToolchainFile = toolchain;
}
for (auto& variable : out->CacheVariables) {
if (variable.second) {
CHECK_EXPAND(out, variable.second->Value, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
}
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile& file, const BuildPreset& preset,
+bool ExpandMacros(const cmCMakePresetsGraph& graph, const BuildPreset& preset,
cm::optional<BuildPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& target : out->Targets) {
- CHECK_EXPAND(out, target, macroExpanders, file.GetVersion(preset))
+ CHECK_EXPAND(out, target, macroExpanders, graph.GetVersion(preset));
}
for (auto& nativeToolOption : out->NativeToolOptions) {
CHECK_EXPAND(out, nativeToolOption, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
}
return true;
}
-bool ExpandMacros(const cmCMakePresetsFile& file, const TestPreset& preset,
+bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset,
cm::optional<TestPreset>& out,
const std::vector<MacroExpander>& macroExpanders)
{
for (auto& overwrite : out->OverwriteConfigurationFile) {
- CHECK_EXPAND(out, overwrite, macroExpanders, file.GetVersion(preset));
+ CHECK_EXPAND(out, overwrite, macroExpanders, graph.GetVersion(preset));
}
if (out->Output) {
CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
}
if (out->Filter) {
if (out->Filter->Include) {
CHECK_EXPAND(out, out->Filter->Include->Name, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
CHECK_EXPAND(out, out->Filter->Include->Label, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
if (out->Filter->Include->Index) {
CHECK_EXPAND(out, out->Filter->Include->Index->IndexFile,
- macroExpanders, file.GetVersion(preset));
+ macroExpanders, graph.GetVersion(preset));
}
}
if (out->Filter->Exclude) {
CHECK_EXPAND(out, out->Filter->Exclude->Name, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
CHECK_EXPAND(out, out->Filter->Exclude->Label, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
if (out->Filter->Exclude->Fixtures) {
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Any, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Setup,
- macroExpanders, file.GetVersion(preset))
+ macroExpanders, graph.GetVersion(preset));
CHECK_EXPAND(out, out->Filter->Exclude->Fixtures->Cleanup,
- macroExpanders, file.GetVersion(preset))
+ macroExpanders, graph.GetVersion(preset));
}
}
}
if (out->Execution) {
CHECK_EXPAND(out, out->Execution->ResourceSpecFile, macroExpanders,
- file.GetVersion(preset))
+ graph.GetVersion(preset));
}
return true;
}
template <class T>
-bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
+bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset,
cm::optional<T>& out)
{
out.emplace(preset);
@@ -313,20 +315,20 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
std::vector<MacroExpander> macroExpanders;
MacroExpander defaultMacroExpander =
- [&file, &preset](const std::string& macroNamespace,
- const std::string& macroName, std::string& macroOut,
- int version) -> ExpandMacroResult {
+ [&graph, &preset](const std::string& macroNamespace,
+ const std::string& macroName, std::string& macroOut,
+ int version) -> ExpandMacroResult {
if (macroNamespace.empty()) {
if (macroName == "sourceDir") {
- macroOut += file.SourceDir;
+ macroOut += graph.SourceDir;
return ExpandMacroResult::Ok;
}
if (macroName == "sourceParentDir") {
- macroOut += cmSystemTools::GetParentDirectory(file.SourceDir);
+ macroOut += cmSystemTools::GetParentDirectory(graph.SourceDir);
return ExpandMacroResult::Ok;
}
if (macroName == "sourceDirName") {
- macroOut += cmSystemTools::GetFilenameName(file.SourceDir);
+ macroOut += cmSystemTools::GetFilenameName(graph.SourceDir);
return ExpandMacroResult::Ok;
}
if (macroName == "presetName") {
@@ -336,7 +338,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
if (macroName == "generator") {
// Generator only makes sense if preset is not hidden.
if (!preset.Hidden) {
- macroOut += file.GetGeneratorForPreset(preset.Name);
+ macroOut += graph.GetGeneratorForPreset(preset.Name);
}
return ExpandMacroResult::Ok;
}
@@ -393,7 +395,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
for (auto& v : out->Environment) {
if (v.second) {
switch (VisitEnv(*v.second, envCycles[v.first], macroExpanders,
- file.GetVersion(preset))) {
+ graph.GetVersion(preset))) {
case ExpandMacroResult::Error:
return false;
case ExpandMacroResult::Ignore:
@@ -408,7 +410,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
if (preset.ConditionEvaluator) {
cm::optional<bool> result;
if (!preset.ConditionEvaluator->Evaluate(
- macroExpanders, file.GetVersion(preset), result)) {
+ macroExpanders, graph.GetVersion(preset), result)) {
return false;
}
if (!result) {
@@ -418,7 +420,7 @@ bool ExpandMacros(const cmCMakePresetsFile& file, const T& preset,
out->ConditionResult = *result;
}
- return ExpandMacros(file, preset, out, macroExpanders);
+ return ExpandMacros(graph, preset, out, macroExpanders);
}
ExpandMacroResult VisitEnv(std::string& value, CycleStatus& status,
@@ -541,7 +543,7 @@ ExpandMacroResult ExpandMacro(std::string& out,
}
}
-bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate(
+bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate(
const std::vector<MacroExpander>& expanders, int version,
cm::optional<bool>& out) const
{
@@ -555,7 +557,7 @@ bool cmCMakePresetsFileInternal::EqualsCondition::Evaluate(
return true;
}
-bool cmCMakePresetsFileInternal::InListCondition::Evaluate(
+bool cmCMakePresetsGraphInternal::InListCondition::Evaluate(
const std::vector<MacroExpander>& expanders, int version,
cm::optional<bool>& out) const
{
@@ -574,7 +576,7 @@ bool cmCMakePresetsFileInternal::InListCondition::Evaluate(
return true;
}
-bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate(
+bool cmCMakePresetsGraphInternal::MatchesCondition::Evaluate(
const std::vector<MacroExpander>& expanders, int version,
cm::optional<bool>& out) const
{
@@ -592,7 +594,7 @@ bool cmCMakePresetsFileInternal::MatchesCondition::Evaluate(
return true;
}
-bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate(
+bool cmCMakePresetsGraphInternal::AnyAllOfCondition::Evaluate(
const std::vector<MacroExpander>& expanders, int version,
cm::optional<bool>& out) const
{
@@ -618,7 +620,7 @@ bool cmCMakePresetsFileInternal::AnyAllOfCondition::Evaluate(
return true;
}
-bool cmCMakePresetsFileInternal::NotCondition::Evaluate(
+bool cmCMakePresetsGraphInternal::NotCondition::Evaluate(
const std::vector<MacroExpander>& expanders, int version,
cm::optional<bool>& out) const
{
@@ -633,9 +635,9 @@ bool cmCMakePresetsFileInternal::NotCondition::Evaluate(
return true;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
- const cmCMakePresetsFile::Preset& parentPreset)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::ConfigurePreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
const ConfigurePreset& parent =
@@ -667,8 +669,8 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetInherit(
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit()
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::ConfigurePreset::VisitPresetBeforeInherit()
{
auto& preset = *this;
if (preset.Environment.count("") != 0) {
@@ -678,8 +680,8 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetBeforeInherit()
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::ConfigurePreset::VisitPresetAfterInherit(int version)
{
auto& preset = *this;
if (!preset.Hidden) {
@@ -706,9 +708,9 @@ cmCMakePresetsFile::ConfigurePreset::VisitPresetAfterInherit(int version)
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::BuildPreset::VisitPresetInherit(
- const cmCMakePresetsFile::Preset& parentPreset)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::BuildPreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
const BuildPreset& parent = static_cast<const BuildPreset&>(parentPreset);
@@ -722,12 +724,15 @@ cmCMakePresetsFile::BuildPreset::VisitPresetInherit(
InheritOptionalValue(preset.CleanFirst, parent.CleanFirst);
InheritOptionalValue(preset.Verbose, parent.Verbose);
InheritVector(preset.NativeToolOptions, parent.NativeToolOptions);
+ if (!preset.ResolvePackageReferences) {
+ preset.ResolvePackageReferences = parent.ResolvePackageReferences;
+ }
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::BuildPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -736,9 +741,9 @@ cmCMakePresetsFile::BuildPreset::VisitPresetAfterInherit(int /* version */)
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::TestPreset::VisitPresetInherit(
- const cmCMakePresetsFile::Preset& parentPreset)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::TestPreset::VisitPresetInherit(
+ const cmCMakePresetsGraph::Preset& parentPreset)
{
auto& preset = *this;
const TestPreset& parent = static_cast<const TestPreset&>(parentPreset);
@@ -836,8 +841,8 @@ cmCMakePresetsFile::TestPreset::VisitPresetInherit(
return ReadFileResult::READ_OK;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(int /* version */)
{
auto& preset = *this;
if (!preset.Hidden && preset.ConfigurePreset.empty()) {
@@ -846,17 +851,17 @@ cmCMakePresetsFile::TestPreset::VisitPresetAfterInherit(int /* version */)
return ReadFileResult::READ_OK;
}
-std::string cmCMakePresetsFile::GetFilename(const std::string& sourceDir)
+std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir)
{
return cmStrCat(sourceDir, "/CMakePresets.json");
}
-std::string cmCMakePresetsFile::GetUserFilename(const std::string& sourceDir)
+std::string cmCMakePresetsGraph::GetUserFilename(const std::string& sourceDir)
{
return cmStrCat(sourceDir, "/CMakeUserPresets.json");
}
-cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
+cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadProjectPresets(
const std::string& sourceDir, bool allowNoFiles)
{
this->SourceDir = sourceDir;
@@ -870,37 +875,42 @@ cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
return result;
}
-cmCMakePresetsFile::ReadFileResult
-cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
+cmCMakePresetsGraph::ReadFileResult
+cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles)
{
bool haveOneFile = false;
+ File* file;
std::string filename = GetUserFilename(this->SourceDir);
+ std::vector<File*> inProgressFiles;
if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(filename, true);
+ auto result = this->ReadJSONFile(filename, RootType::User,
+ ReadReason::Root, inProgressFiles, file);
if (result != ReadFileResult::READ_OK) {
return result;
}
haveOneFile = true;
- }
-
- filename = GetFilename(this->SourceDir);
- if (cmSystemTools::FileExists(filename)) {
- auto result = this->ReadJSONFile(filename, false);
- if (result != ReadFileResult::READ_OK) {
- return result;
+ } else {
+ filename = GetFilename(this->SourceDir);
+ if (cmSystemTools::FileExists(filename)) {
+ auto result = this->ReadJSONFile(
+ filename, RootType::Project, ReadReason::Root, inProgressFiles, file);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ haveOneFile = true;
}
- haveOneFile = true;
}
+ assert(inProgressFiles.empty());
if (!haveOneFile) {
return allowNoFiles ? ReadFileResult::READ_OK
: ReadFileResult::FILE_NOT_FOUND;
}
- CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this))
- CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this))
- CHECK_OK(ComputePresetInheritance(this->TestPresets, *this))
+ CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this));
+ CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this));
+ CHECK_OK(ComputePresetInheritance(this->TestPresets, *this));
for (auto& it : this->ConfigurePresets) {
if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) {
@@ -915,6 +925,10 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
if (configurePreset == this->ConfigurePresets.end()) {
return ReadFileResult::INVALID_CONFIGURE_PRESET;
}
+ if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
+ configurePreset->second.Unexpanded.OriginFile)) {
+ return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
+ }
if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
it.second.Unexpanded.Environment.insert(
@@ -935,6 +949,10 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
if (configurePreset == this->ConfigurePresets.end()) {
return ReadFileResult::INVALID_CONFIGURE_PRESET;
}
+ if (!it.second.Unexpanded.OriginFile->ReachableFiles.count(
+ configurePreset->second.Unexpanded.OriginFile)) {
+ return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE;
+ }
if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) {
it.second.Unexpanded.Environment.insert(
@@ -951,7 +969,7 @@ cmCMakePresetsFile::ReadProjectPresetsInternal(bool allowNoFiles)
return ReadFileResult::READ_OK;
}
-const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
+const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result)
{
switch (result) {
case ReadFileResult::READ_OK:
@@ -982,13 +1000,19 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
return "Duplicate presets";
case ReadFileResult::CYCLIC_PRESET_INHERITANCE:
return "Cyclic preset inheritance";
- case ReadFileResult::USER_PRESET_INHERITANCE:
- return "Project preset inherits from user preset";
+ case ReadFileResult::INHERITED_PRESET_UNREACHABLE_FROM_FILE:
+ return "Inherited preset is unreachable from preset's file";
+ case ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE:
+ return "Configure preset is unreachable from preset's file";
case ReadFileResult::INVALID_MACRO_EXPANSION:
return "Invalid macro expansion";
case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED:
return "File version must be 2 or higher for build and test preset "
"support.";
+ case ReadFileResult::INCLUDE_UNSUPPORTED:
+ return "File version must be 4 or higher for include support";
+ case ReadFileResult::INVALID_INCLUDE:
+ return "Invalid \"include\" field";
case ReadFileResult::INVALID_CONFIGURE_PRESET:
return "Invalid \"configurePreset\" field";
case ReadFileResult::INSTALL_PREFIX_UNSUPPORTED:
@@ -1001,12 +1025,14 @@ const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
case ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED:
return "File version must be 3 or higher for toolchainFile preset "
"support.";
+ case ReadFileResult::CYCLIC_INCLUDE:
+ return "Cyclic include among preset files";
}
return "Unknown error";
}
-void cmCMakePresetsFile::ClearPresets()
+void cmCMakePresetsGraph::ClearPresets()
{
this->ConfigurePresets.clear();
this->BuildPresets.clear();
@@ -1015,10 +1041,12 @@ void cmCMakePresetsFile::ClearPresets()
this->ConfigurePresetOrder.clear();
this->BuildPresetOrder.clear();
this->TestPresetOrder.clear();
+
+ this->Files.clear();
}
-void cmCMakePresetsFile::PrintPresets(
- const std::vector<const cmCMakePresetsFile::Preset*>& presets)
+void cmCMakePresetsGraph::PrintPresets(
+ const std::vector<const cmCMakePresetsGraph::Preset*>& presets)
{
if (presets.empty()) {
return;
@@ -1026,8 +1054,8 @@ void cmCMakePresetsFile::PrintPresets(
auto longestPresetName =
std::max_element(presets.begin(), presets.end(),
- [](const cmCMakePresetsFile::Preset* a,
- const cmCMakePresetsFile::Preset* b) {
+ [](const cmCMakePresetsGraph::Preset* a,
+ const cmCMakePresetsGraph::Preset* b) {
return a->Name.length() < b->Name.length();
});
auto longestLength = (*longestPresetName)->Name.length();
@@ -1045,67 +1073,67 @@ void cmCMakePresetsFile::PrintPresets(
}
}
-void cmCMakePresetsFile::PrintConfigurePresetList() const
+void cmCMakePresetsGraph::PrintConfigurePresetList() const
{
PrintConfigurePresetList([](const ConfigurePreset&) { return true; });
}
-void cmCMakePresetsFile::PrintConfigurePresetList(
+void cmCMakePresetsGraph::PrintConfigurePresetList(
const std::function<bool(const ConfigurePreset&)>& filter) const
{
- std::vector<const cmCMakePresetsFile::Preset*> presets;
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->ConfigurePresetOrder) {
auto const& preset = this->ConfigurePresets.at(p);
if (!preset.Unexpanded.Hidden && preset.Expanded &&
preset.Expanded->ConditionResult && filter(preset.Unexpanded)) {
presets.push_back(
- static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
}
}
if (!presets.empty()) {
std::cout << "Available configure presets:\n\n";
- cmCMakePresetsFile::PrintPresets(presets);
+ cmCMakePresetsGraph::PrintPresets(presets);
}
}
-void cmCMakePresetsFile::PrintBuildPresetList() const
+void cmCMakePresetsGraph::PrintBuildPresetList() const
{
- std::vector<const cmCMakePresetsFile::Preset*> presets;
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->BuildPresetOrder) {
auto const& preset = this->BuildPresets.at(p);
if (!preset.Unexpanded.Hidden && preset.Expanded &&
preset.Expanded->ConditionResult) {
presets.push_back(
- static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
}
}
if (!presets.empty()) {
std::cout << "Available build presets:\n\n";
- cmCMakePresetsFile::PrintPresets(presets);
+ cmCMakePresetsGraph::PrintPresets(presets);
}
}
-void cmCMakePresetsFile::PrintTestPresetList() const
+void cmCMakePresetsGraph::PrintTestPresetList() const
{
- std::vector<const cmCMakePresetsFile::Preset*> presets;
+ std::vector<const cmCMakePresetsGraph::Preset*> presets;
for (auto const& p : this->TestPresetOrder) {
auto const& preset = this->TestPresets.at(p);
if (!preset.Unexpanded.Hidden && preset.Expanded &&
preset.Expanded->ConditionResult) {
presets.push_back(
- static_cast<const cmCMakePresetsFile::Preset*>(&preset.Unexpanded));
+ static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded));
}
}
if (!presets.empty()) {
std::cout << "Available test presets:\n\n";
- cmCMakePresetsFile::PrintPresets(presets);
+ cmCMakePresetsGraph::PrintPresets(presets);
}
}
-void cmCMakePresetsFile::PrintAllPresets() const
+void cmCMakePresetsGraph::PrintAllPresets() const
{
this->PrintConfigurePresetList();
std::cout << std::endl;
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsGraph.h
index 7aa9b6a..9d6c61a 100644
--- a/Source/cmCMakePresetsFile.h
+++ b/Source/cmCMakePresetsGraph.h
@@ -8,12 +8,15 @@
#include <map>
#include <memory>
#include <string>
+#include <unordered_set>
#include <utility>
#include <vector>
#include <cm/optional>
-class cmCMakePresetsFile
+enum class PackageResolveMode;
+
+class cmCMakePresetsGraph
{
public:
enum class ReadFileResult
@@ -32,14 +35,18 @@ public:
INVALID_VARIABLE,
DUPLICATE_PRESETS,
CYCLIC_PRESET_INHERITANCE,
- USER_PRESET_INHERITANCE,
+ INHERITED_PRESET_UNREACHABLE_FROM_FILE,
+ CONFIGURE_PRESET_UNREACHABLE_FROM_FILE,
INVALID_MACRO_EXPANSION,
BUILD_TEST_PRESETS_UNSUPPORTED,
+ INCLUDE_UNSUPPORTED,
+ INVALID_INCLUDE,
INVALID_CONFIGURE_PRESET,
INSTALL_PREFIX_UNSUPPORTED,
INVALID_CONDITION,
CONDITION_UNSUPPORTED,
TOOLCHAIN_FILE_UNSUPPORTED,
+ CYCLIC_INCLUDE,
};
enum class ArchToolsetStrategy
@@ -57,25 +64,36 @@ public:
class Condition;
+ class File
+ {
+ public:
+ std::string Filename;
+ int Version;
+
+ std::unordered_set<File*> ReachableFiles;
+ };
+
class Preset
{
public:
-#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ Preset() = default;
+ Preset(Preset&& /*other*/) = default;
+ Preset(const Preset& /*other*/) = default;
+ Preset& operator=(const Preset& /*other*/) = default;
+ virtual ~Preset() = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ Preset& operator=(Preset&& /*other*/) = default;
+#else
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
- // assignment operator throwing an exception when it shouldn't. Disable the
- // move assignment operator until C++17 is enabled.
- // Explicitly defining a copy assignment operator prevents the compiler
- // from automatically generating a move assignment operator.
- Preset& operator=(const Preset& /*other*/) = default;
+ // assignment operator throwing an exception when it shouldn't.
+ Preset& operator=(Preset&& /*other*/) = delete;
#endif
- virtual ~Preset() = default;
-
std::string Name;
std::vector<std::string> Inherits;
bool Hidden;
- bool User;
+ File* OriginFile;
std::string DisplayName;
std::string Description;
@@ -99,14 +117,18 @@ public:
class ConfigurePreset : public Preset
{
public:
-#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ ConfigurePreset() = default;
+ ConfigurePreset(ConfigurePreset&& /*other*/) = default;
+ ConfigurePreset(const ConfigurePreset& /*other*/) = default;
+ ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default;
+ ~ConfigurePreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ ConfigurePreset& operator=(ConfigurePreset&& /*other*/) = default;
+#else
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
- // assignment operator throwing an exception when it shouldn't. Disable the
- // move assignment operator until C++17 is enabled.
- // Explicitly defining a copy assignment operator prevents the compiler
- // from automatically generating a move assignment operator.
- ConfigurePreset& operator=(const ConfigurePreset& /*other*/) = default;
+ // assignment operator throwing an exception when it shouldn't.
+ ConfigurePreset& operator=(ConfigurePreset&& /*other*/) = delete;
#endif
std::string Generator;
@@ -140,14 +162,18 @@ public:
class BuildPreset : public Preset
{
public:
-#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ BuildPreset() = default;
+ BuildPreset(BuildPreset&& /*other*/) = default;
+ BuildPreset(const BuildPreset& /*other*/) = default;
+ BuildPreset& operator=(const BuildPreset& /*other*/) = default;
+ ~BuildPreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ BuildPreset& operator=(BuildPreset&& /*other*/) = default;
+#else
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
- // assignment operator throwing an exception when it shouldn't. Disable the
- // move assignment operator until C++17 is enabled.
- // Explicitly defining a copy assignment operator prevents the compiler
- // from automatically generating a move assignment operator.
- BuildPreset& operator=(const BuildPreset& /*other*/) = default;
+ // assignment operator throwing an exception when it shouldn't.
+ BuildPreset& operator=(BuildPreset&& /*other*/) = delete;
#endif
std::string ConfigurePreset;
@@ -158,6 +184,7 @@ public:
cm::optional<bool> CleanFirst;
cm::optional<bool> Verbose;
std::vector<std::string> NativeToolOptions;
+ cm::optional<PackageResolveMode> ResolvePackageReferences;
ReadFileResult VisitPresetInherit(const Preset& parent) override;
ReadFileResult VisitPresetAfterInherit(int /* version */) override;
@@ -166,14 +193,18 @@ public:
class TestPreset : public Preset
{
public:
-#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ TestPreset() = default;
+ TestPreset(TestPreset&& /*other*/) = default;
+ TestPreset(const TestPreset& /*other*/) = default;
+ TestPreset& operator=(const TestPreset& /*other*/) = default;
+ ~TestPreset() override = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ TestPreset& operator=(TestPreset&& /*other*/) = default;
+#else
// The move assignment operators for several STL classes did not become
// noexcept until C++17, which causes some tools to warn about this move
- // assignment operator throwing an exception when it shouldn't. Disable the
- // move assignment operator until C++17 is enabled.
- // Explicitly defining a copy assignment operator prevents the compiler
- // from automatically generating a move assignment operator.
- TestPreset& operator=(const TestPreset& /*other*/) = default;
+ // assignment operator throwing an exception when it shouldn't.
+ TestPreset& operator=(TestPreset&& /*other*/) = delete;
#endif
struct OutputOptions
@@ -307,12 +338,11 @@ public:
std::vector<std::string> TestPresetOrder;
std::string SourceDir;
- int Version;
- int UserVersion;
+ std::vector<std::unique_ptr<File>> Files;
int GetVersion(const Preset& preset) const
{
- return preset.User ? this->UserVersion : this->Version;
+ return preset.OriginFile->Version;
}
static std::string GetFilename(const std::string& sourceDir);
@@ -349,7 +379,7 @@ public:
}
static void PrintPresets(
- const std::vector<const cmCMakePresetsFile::Preset*>& presets);
+ const std::vector<const cmCMakePresetsGraph::Preset*>& presets);
void PrintConfigurePresetList() const;
void PrintConfigurePresetList(
const std::function<bool(const ConfigurePreset&)>& filter) const;
@@ -358,7 +388,22 @@ public:
void PrintAllPresets() const;
private:
+ enum class RootType
+ {
+ Project,
+ User,
+ };
+
+ enum class ReadReason
+ {
+ Root,
+ Included,
+ };
+
ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles);
- ReadFileResult ReadJSONFile(const std::string& filename, bool user);
+ ReadFileResult ReadJSONFile(const std::string& filename, RootType rootType,
+ ReadReason readReason,
+ std::vector<File*>& inProgressFiles,
+ File*& file);
void ClearPresets();
};
diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h
new file mode 100644
index 0000000..f7c7349
--- /dev/null
+++ b/Source/cmCMakePresetsGraphInternal.h
@@ -0,0 +1,163 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmJSONHelpers.h"
+
+#define CHECK_OK(expr) \
+ do { \
+ auto _result = expr; \
+ if (_result != ReadFileResult::READ_OK) \
+ return _result; \
+ } while (false)
+
+namespace cmCMakePresetsGraphInternal {
+enum class ExpandMacroResult
+{
+ Ok,
+ Ignore,
+ Error,
+};
+
+using MacroExpander = std::function<ExpandMacroResult(
+ const std::string&, const std::string&, std::string&, int version)>;
+}
+
+class cmCMakePresetsGraph::Condition
+{
+public:
+ virtual ~Condition() = default;
+
+ virtual bool Evaluate(
+ const std::vector<cmCMakePresetsGraphInternal::MacroExpander>& expanders,
+ int version, cm::optional<bool>& out) const = 0;
+ virtual bool IsNull() const { return false; }
+};
+
+namespace cmCMakePresetsGraphInternal {
+
+class NullCondition : public cmCMakePresetsGraph::Condition
+{
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = true;
+ return true;
+ }
+
+ bool IsNull() const override { return true; }
+};
+
+class ConstCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& /*expanders*/,
+ int /*version*/, cm::optional<bool>& out) const override
+ {
+ out = this->Value;
+ return true;
+ }
+
+ bool Value;
+};
+
+class EqualsCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string Lhs;
+ std::string Rhs;
+};
+
+class InListCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::vector<std::string> List;
+};
+
+class MatchesCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::string String;
+ std::string Regex;
+};
+
+class AnyAllOfCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::vector<std::unique_ptr<Condition>> Conditions;
+ bool StopValue;
+};
+
+class NotCondition : public cmCMakePresetsGraph::Condition
+{
+public:
+ bool Evaluate(const std::vector<MacroExpander>& expanders, int version,
+ cm::optional<bool>& out) const override;
+
+ std::unique_ptr<Condition> SubCondition;
+};
+
+cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
+ std::string& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
+ std::vector<std::string>& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
+ cm::optional<bool>& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
+ cm::optional<int>& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
+ std::vector<int>& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult ConfigurePresetsHelper(
+ std::vector<cmCMakePresetsGraph::ConfigurePreset>& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper(
+ std::vector<cmCMakePresetsGraph::BuildPreset>& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
+ std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value);
+
+cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper(
+ cmCMakePresetsGraph::ReadFileResult error);
+
+cmCMakePresetsGraph::ReadFileResult PresetConditionHelper(
+ std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
+ const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult PresetVectorOneOrMoreStringHelper(
+ std::vector<std::string>& out, const Json::Value* value);
+
+cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
+ std::map<std::string, cm::optional<std::string>>& out,
+ const Json::Value* value);
+}
diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx
new file mode 100644
index 0000000..85cf5be
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSON.cxx
@@ -0,0 +1,615 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using CacheVariable = cmCMakePresetsGraph::CacheVariable;
+using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
+using BuildPreset = cmCMakePresetsGraph::BuildPreset;
+using TestPreset = cmCMakePresetsGraph::TestPreset;
+using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
+
+constexpr int MIN_VERSION = 1;
+constexpr int MAX_VERSION = 4;
+
+struct CMakeVersion
+{
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+ unsigned int Patch = 0;
+};
+
+struct RootPresets
+{
+ CMakeVersion CMakeMinimumRequired;
+ std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets;
+ std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets;
+ std::vector<cmCMakePresetsGraph::TestPreset> TestPresets;
+ std::vector<std::string> Include;
+};
+
+std::unique_ptr<cmCMakePresetsGraphInternal::NotCondition> InvertCondition(
+ std::unique_ptr<cmCMakePresetsGraph::Condition> condition)
+{
+ auto retval = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
+ retval->SubCondition = std::move(condition);
+ return retval;
+}
+
+auto const ConditionStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION);
+
+auto const ConditionStringListHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CONDITION,
+ ConditionStringHelper);
+
+auto const ConstConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::ConstCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("value"_s, &cmCMakePresetsGraphInternal::ConstCondition::Value,
+ ConditionBoolHelper, true);
+
+auto const EqualsConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::EqualsCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("lhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Lhs,
+ ConditionStringHelper, true)
+ .Bind("rhs"_s, &cmCMakePresetsGraphInternal::EqualsCondition::Rhs,
+ ConditionStringHelper, true);
+
+auto const InListConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::InListCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsGraphInternal::InListCondition::String,
+ ConditionStringHelper, true)
+ .Bind("list"_s, &cmCMakePresetsGraphInternal::InListCondition::List,
+ ConditionStringListHelper, true);
+
+auto const MatchesConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::MatchesCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("string"_s, &cmCMakePresetsGraphInternal::MatchesCondition::String,
+ ConditionStringHelper, true)
+ .Bind("regex"_s, &cmCMakePresetsGraphInternal::MatchesCondition::Regex,
+ ConditionStringHelper, true);
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
+ const Json::Value* value);
+
+auto const ListConditionVectorHelper =
+ cmJSONVectorHelper<std::unique_ptr<cmCMakePresetsGraph::Condition>,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION,
+ SubConditionHelper);
+auto const AnyAllOfConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::AnyAllOfCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("conditions"_s,
+ &cmCMakePresetsGraphInternal::AnyAllOfCondition::Conditions,
+ ListConditionVectorHelper);
+
+auto const NotConditionHelper =
+ cmJSONObjectHelper<cmCMakePresetsGraphInternal::NotCondition,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_CONDITION, false)
+ .Bind<std::string>("type"_s, nullptr, ConditionStringHelper, true)
+ .Bind("condition"_s,
+ &cmCMakePresetsGraphInternal::NotCondition::SubCondition,
+ SubConditionHelper);
+
+ReadFileResult ConditionHelper(
+ std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out.reset();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
+ c->Value = value->asBool();
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isNull()) {
+ out = cm::make_unique<cmCMakePresetsGraphInternal::NullCondition>();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ if (!value->isMember("type")) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+
+ if (!(*value)["type"].isString()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ auto type = (*value)["type"].asString();
+
+ if (type == "const") {
+ auto c = cm::make_unique<cmCMakePresetsGraphInternal::ConstCondition>();
+ CHECK_OK(ConstConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "equals" || type == "notEquals") {
+ auto c = cm::make_unique<cmCMakePresetsGraphInternal::EqualsCondition>();
+ CHECK_OK(EqualsConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notEquals") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "inList" || type == "notInList") {
+ auto c = cm::make_unique<cmCMakePresetsGraphInternal::InListCondition>();
+ CHECK_OK(InListConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notInList") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "matches" || type == "notMatches") {
+ auto c =
+ cm::make_unique<cmCMakePresetsGraphInternal::MatchesCondition>();
+ CHECK_OK(MatchesConditionHelper(*c, value));
+ out = std::move(c);
+ if (type == "notMatches") {
+ out = InvertCondition(std::move(out));
+ }
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "anyOf" || type == "allOf") {
+ auto c =
+ cm::make_unique<cmCMakePresetsGraphInternal::AnyAllOfCondition>();
+ c->StopValue = (type == "anyOf");
+ CHECK_OK(AnyAllOfConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+
+ if (type == "not") {
+ auto c = cm::make_unique<cmCMakePresetsGraphInternal::NotCondition>();
+ CHECK_OK(NotConditionHelper(*c, value));
+ out = std::move(c);
+ return ReadFileResult::READ_OK;
+ }
+ }
+
+ return ReadFileResult::INVALID_CONDITION;
+}
+
+ReadFileResult SubConditionHelper(
+ std::unique_ptr<cmCMakePresetsGraph::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ if (ptr && ptr->IsNull()) {
+ return ReadFileResult::INVALID_CONDITION;
+ }
+ out = std::move(ptr);
+ return result;
+}
+
+ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
+ const Json::Value* value)
+{
+ if (!value || value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
+ ReadFileResult::NO_VERSION, VersionIntHelper);
+
+auto const RootVersionHelper =
+ cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_ROOT)
+ .Bind("version"_s, VersionHelper, false);
+
+auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const CMakeVersionHelper =
+ cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
+ .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
+ .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
+ .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
+
+auto const IncludeHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE);
+
+auto const IncludeVectorHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_INCLUDE, IncludeHelper);
+
+auto const RootPresetsHelper =
+ cmJSONObjectHelper<RootPresets, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
+ .Bind<int>("version"_s, nullptr, VersionHelper)
+ .Bind("configurePresets"_s, &RootPresets::ConfigurePresets,
+ cmCMakePresetsGraphInternal::ConfigurePresetsHelper, false)
+ .Bind("buildPresets"_s, &RootPresets::BuildPresets,
+ cmCMakePresetsGraphInternal::BuildPresetsHelper, false)
+ .Bind("testPresets"_s, &RootPresets::TestPresets,
+ cmCMakePresetsGraphInternal::TestPresetsHelper, false)
+ .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
+ CMakeVersionHelper, false)
+ .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false)
+ .Bind<std::nullptr_t>(
+ "vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(ReadFileResult::INVALID_ROOT),
+ false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult PresetStringHelper(
+ std::string& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetVectorStringHelper(
+ std::vector<std::string>& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ cmCMakePresetsGraphInternal::PresetStringHelper);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetBoolHelper(bool& out,
+ const Json::Value* value)
+{
+ static auto const helper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetOptionalBoolHelper(
+ cm::optional<bool>& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONOptionalHelper<bool, ReadFileResult>(
+ ReadFileResult::READ_OK, PresetBoolHelper);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetIntHelper(int& out,
+ const Json::Value* value)
+{
+ static auto const helper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetOptionalIntHelper(
+ cm::optional<int>& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONOptionalHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, PresetIntHelper);
+
+ return helper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult PresetVectorIntHelper(
+ std::vector<int>& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONVectorHelper<int, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, PresetIntHelper);
+
+ return helper(out, value);
+}
+
+cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
+{
+ return [error](std::nullptr_t& /*out*/,
+ const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isObject()) {
+ return error;
+ }
+
+ return ReadFileResult::READ_OK;
+ };
+}
+
+ReadFileResult PresetConditionHelper(
+ std::shared_ptr<cmCMakePresetsGraph::Condition>& out,
+ const Json::Value* value)
+{
+ std::unique_ptr<cmCMakePresetsGraph::Condition> ptr;
+ auto result = ConditionHelper(ptr, value);
+ out = std::move(ptr);
+ return result;
+}
+
+ReadFileResult PresetVectorOneOrMoreStringHelper(std::vector<std::string>& out,
+ const Json::Value* value)
+{
+ out.clear();
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.push_back(value->asString());
+ return ReadFileResult::READ_OK;
+ }
+
+ return PresetVectorStringHelper(out, value);
+}
+
+cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper(
+ std::map<std::string, cm::optional<std::string>>& out,
+ const Json::Value* value)
+{
+ static auto const helper =
+ cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ EnvironmentHelper);
+
+ return helper(out, value);
+}
+}
+
+cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile(
+ const std::string& filename, RootType rootType, ReadReason readReason,
+ std::vector<File*>& inProgressFiles, File*& file)
+{
+ ReadFileResult result;
+
+ for (auto const& f : this->Files) {
+ if (cmSystemTools::SameFile(filename, f->Filename)) {
+ file = f.get();
+ auto fileIt =
+ std::find(inProgressFiles.begin(), inProgressFiles.end(), file);
+ if (fileIt != inProgressFiles.end()) {
+ return cmCMakePresetsGraph::ReadFileResult::CYCLIC_INCLUDE;
+ }
+
+ return cmCMakePresetsGraph::ReadFileResult::READ_OK;
+ }
+ }
+
+ cmsys::ifstream fin(filename.c_str());
+ if (!fin) {
+ return ReadFileResult::FILE_NOT_FOUND;
+ }
+ // If there's a BOM, toss it.
+ cmsys::FStream::ReadBOM(fin);
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ Json::CharReaderBuilder::strictMode(&builder.settings_);
+ if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ return ReadFileResult::JSON_PARSE_ERROR;
+ }
+
+ int v = 0;
+ if ((result = RootVersionHelper(v, &root)) != ReadFileResult::READ_OK) {
+ return result;
+ }
+ if (v < MIN_VERSION || v > MAX_VERSION) {
+ return ReadFileResult::UNRECOGNIZED_VERSION;
+ }
+
+ // Support for build and test presets added in version 2.
+ if (v < 2 &&
+ (root.isMember("buildPresets") || root.isMember("testPresets"))) {
+ return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED;
+ }
+
+ // Support for include added in version 4.
+ if (v < 4 && root.isMember("include")) {
+ return ReadFileResult::INCLUDE_UNSUPPORTED;
+ }
+
+ RootPresets presets;
+ if ((result = RootPresetsHelper(presets, &root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ unsigned int currentMajor = cmVersion::GetMajorVersion();
+ unsigned int currentMinor = cmVersion::GetMinorVersion();
+ unsigned int currentPatch = cmVersion::GetPatchVersion();
+ auto const& required = presets.CMakeMinimumRequired;
+ if (required.Major > currentMajor ||
+ (required.Major == currentMajor &&
+ (required.Minor > currentMinor ||
+ (required.Minor == currentMinor &&
+ (required.Patch > currentPatch))))) {
+ return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
+ }
+
+ auto filePtr = cm::make_unique<File>();
+ file = filePtr.get();
+ this->Files.emplace_back(std::move(filePtr));
+ inProgressFiles.emplace_back(file);
+ file->Filename = filename;
+ file->Version = v;
+ file->ReachableFiles.insert(file);
+
+ for (auto& preset : presets.ConfigurePresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<ConfigurePreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->ConfigurePresets
+ .emplace(std::make_pair(preset.Name, presetPair))
+ .second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for installDir presets added in version 3.
+ if (v < 3 && !preset.InstallDir.empty()) {
+ return ReadFileResult::INSTALL_PREFIX_UNSUPPORTED;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ // Support for toolchainFile presets added in version 3.
+ if (v < 3 && !preset.ToolchainFile.empty()) {
+ return ReadFileResult::TOOLCHAIN_FILE_UNSUPPORTED;
+ }
+
+ this->ConfigurePresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.BuildPresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<BuildPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->BuildPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->BuildPresetOrder.push_back(preset.Name);
+ }
+
+ for (auto& preset : presets.TestPresets) {
+ preset.OriginFile = file;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ PresetPair<TestPreset> presetPair;
+ presetPair.Unexpanded = preset;
+ presetPair.Expanded = cm::nullopt;
+ if (!this->TestPresets.emplace(preset.Name, presetPair).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+
+ // Support for conditions added in version 3.
+ if (v < 3 && preset.ConditionEvaluator) {
+ return ReadFileResult::CONDITION_UNSUPPORTED;
+ }
+
+ this->TestPresetOrder.push_back(preset.Name);
+ }
+
+ auto const includeFile = [this, &inProgressFiles, file](
+ const std::string& include, RootType rootType2,
+ ReadReason readReason2) -> ReadFileResult {
+ ReadFileResult r;
+ File* includedFile;
+ if ((r = this->ReadJSONFile(include, rootType2, readReason2,
+ inProgressFiles, includedFile)) !=
+ ReadFileResult::READ_OK) {
+ return r;
+ }
+
+ file->ReachableFiles.insert(includedFile->ReachableFiles.begin(),
+ includedFile->ReachableFiles.end());
+ return ReadFileResult::READ_OK;
+ };
+
+ for (auto include : presets.Include) {
+ if (!cmSystemTools::FileIsFullPath(include)) {
+ auto directory = cmSystemTools::GetFilenamePath(filename);
+ include = cmStrCat(directory, '/', include);
+ }
+
+ if ((result = includeFile(include, rootType, ReadReason::Included)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+ }
+
+ if (rootType == RootType::User && readReason == ReadReason::Root) {
+ auto cmakePresetsFilename = GetFilename(this->SourceDir);
+ if (cmSystemTools::FileExists(cmakePresetsFilename)) {
+ if ((result = includeFile(cmakePresetsFilename, RootType::Project,
+ ReadReason::Root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+ }
+ }
+
+ inProgressFiles.pop_back();
+ return ReadFileResult::READ_OK;
+}
diff --git a/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx
new file mode 100644
index 0000000..eefe2fe
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONBuildPresets.cxx
@@ -0,0 +1,108 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmBuildOptions.h"
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using BuildPreset = cmCMakePresetsGraph::BuildPreset;
+
+ReadFileResult PackageResolveModeHelper(cm::optional<PackageResolveMode>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "on") {
+ out = PackageResolveMode::Force;
+ } else if (value->asString() == "off") {
+ out = PackageResolveMode::Disable;
+ } else if (value->asString() == "only") {
+ out = PackageResolveMode::OnlyResolve;
+ } else {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ return ReadFileResult::READ_OK;
+}
+
+std::function<ReadFileResult(BuildPreset&, const Json::Value*)> const
+ ResolvePackageReferencesHelper =
+ [](BuildPreset& out, const Json::Value* value) -> ReadFileResult {
+ return PackageResolveModeHelper(out.ResolvePackageReferences, value);
+};
+
+auto const BuildPresetHelper =
+ cmJSONObjectHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &BuildPreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind("inherits"_s, &BuildPreset::Inherits,
+ cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+ false)
+ .Bind("hidden"_s, &BuildPreset::Hidden,
+ cmCMakePresetsGraphInternal::PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &BuildPreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &BuildPreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("environment"_s, &BuildPreset::Environment,
+ cmCMakePresetsGraphInternal::EnvironmentMapHelper, false)
+ .Bind("configurePreset"_s, &BuildPreset::ConfigurePreset,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &BuildPreset::InheritConfigureEnvironment,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("jobs"_s, &BuildPreset::Jobs,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("targets"_s, &BuildPreset::Targets,
+ cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+ false)
+ .Bind("configuration"_s, &BuildPreset::Configuration,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("cleanFirst"_s, &BuildPreset::CleanFirst,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("verbose"_s, &BuildPreset::Verbose,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("nativeToolOptions"_s, &BuildPreset::NativeToolOptions,
+ cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+ .Bind("condition"_s, &BuildPreset::ConditionEvaluator,
+ cmCMakePresetsGraphInternal::PresetConditionHelper, false)
+ .Bind("resolvePackageReferences"_s, ResolvePackageReferencesHelper, false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+ReadFileResult BuildPresetsHelper(std::vector<BuildPreset>& out,
+ const Json::Value* value)
+{
+ static auto const helper = cmJSONVectorHelper<BuildPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ BuildPresetHelper);
+
+ return helper(out, value);
+}
+}
diff --git a/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx
new file mode 100644
index 0000000..0f44546
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONConfigurePresets.cxx
@@ -0,0 +1,228 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using CacheVariable = cmCMakePresetsGraph::CacheVariable;
+using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset;
+using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy;
+
+ReadFileResult ArchToolsetStrategyHelper(
+ cm::optional<ArchToolsetStrategy>& out, const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "set") {
+ out = ArchToolsetStrategy::Set;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "external") {
+ out = ArchToolsetStrategy::External;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+std::function<ReadFileResult(ConfigurePreset&, const Json::Value*)>
+ArchToolsetHelper(
+ std::string ConfigurePreset::*valueField,
+ cm::optional<ArchToolsetStrategy> ConfigurePreset::*strategyField)
+{
+ auto const objectHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("value", valueField,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("strategy", strategyField, ArchToolsetStrategyHelper, false);
+ return [valueField, strategyField, objectHelper](
+ ConfigurePreset& out, const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ (out.*valueField).clear();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.*valueField = value->asString();
+ out.*strategyField = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return objectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+ };
+}
+
+auto const ArchitectureHelper = ArchToolsetHelper(
+ &ConfigurePreset::Architecture, &ConfigurePreset::ArchitectureStrategy);
+auto const ToolsetHelper = ArchToolsetHelper(
+ &ConfigurePreset::Toolset, &ConfigurePreset::ToolsetStrategy);
+
+auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+ReadFileResult VariableValueHelper(std::string& out, const Json::Value* value)
+{
+ if (!value) {
+ out.clear();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isBool()) {
+ out = value->asBool() ? "TRUE" : "FALSE";
+ return ReadFileResult::READ_OK;
+ }
+
+ return VariableStringHelper(out, value);
+}
+
+auto const VariableObjectHelper =
+ cmJSONObjectHelper<CacheVariable, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
+ .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
+ .Bind("value"_s, &CacheVariable::Value, VariableValueHelper);
+
+ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
+ const Json::Value* value)
+{
+ if (value->isBool()) {
+ out = CacheVariable{
+ /*Type=*/"BOOL",
+ /*Value=*/value->asBool() ? "TRUE" : "FALSE",
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = CacheVariable{
+ /*Type=*/"",
+ /*Value=*/value->asString(),
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isObject()) {
+ out.emplace();
+ return VariableObjectHelper(*out, value);
+ }
+ if (value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_VARIABLE;
+}
+
+auto const VariablesHelper =
+ cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PresetWarningsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::WarnDev,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::WarnDeprecated,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("uninitialized"_s, &ConfigurePreset::WarnUninitialized,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("unusedCli"_s, &ConfigurePreset::WarnUnusedCli,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("systemVars"_s, &ConfigurePreset::WarnSystemVars,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+
+auto const PresetErrorsHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &ConfigurePreset::ErrorDev,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &ConfigurePreset::ErrorDeprecated,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+
+auto const PresetDebugHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("output"_s, &ConfigurePreset::DebugOutput,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("tryCompile"_s, &ConfigurePreset::DebugTryCompile,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("find"_s, &ConfigurePreset::DebugFind,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false);
+
+auto const ConfigurePresetHelper =
+ cmJSONObjectHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &ConfigurePreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind("inherits"_s, &ConfigurePreset::Inherits,
+ cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+ false)
+ .Bind("hidden"_s, &ConfigurePreset::Hidden,
+ cmCMakePresetsGraphInternal::PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &ConfigurePreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &ConfigurePreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("generator"_s, &ConfigurePreset::Generator,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("architecture"_s, ArchitectureHelper, false)
+ .Bind("toolset"_s, ToolsetHelper, false)
+ .Bind("toolchainFile"_s, &ConfigurePreset::ToolchainFile,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("binaryDir"_s, &ConfigurePreset::BinaryDir,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("installDir"_s, &ConfigurePreset::InstallDir,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind<std::string>("cmakeExecutable"_s, nullptr,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("cacheVariables"_s, &ConfigurePreset::CacheVariables,
+ VariablesHelper, false)
+ .Bind("environment"_s, &ConfigurePreset::Environment,
+ cmCMakePresetsGraphInternal::EnvironmentMapHelper, false)
+ .Bind("warnings"_s, PresetWarningsHelper, false)
+ .Bind("errors"_s, PresetErrorsHelper, false)
+ .Bind("debug"_s, PresetDebugHelper, false)
+ .Bind("condition"_s, &ConfigurePreset::ConditionEvaluator,
+ cmCMakePresetsGraphInternal::PresetConditionHelper, false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+ReadFileResult ConfigurePresetsHelper(std::vector<ConfigurePreset>& out,
+ const Json::Value* value)
+{
+ static auto const helper =
+ cmJSONVectorHelper<ConfigurePreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ ConfigurePresetHelper);
+
+ return helper(out, value);
+}
+}
diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
new file mode 100644
index 0000000..4d6474a
--- /dev/null
+++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx
@@ -0,0 +1,360 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+#include <cm3p/json/value.h>
+
+#include "cmCMakePresetsGraph.h"
+#include "cmCMakePresetsGraphInternal.h"
+#include "cmJSONHelpers.h"
+
+namespace {
+using ReadFileResult = cmCMakePresetsGraph::ReadFileResult;
+using TestPreset = cmCMakePresetsGraph::TestPreset;
+
+ReadFileResult TestPresetOutputVerbosityHelper(
+ TestPreset::OutputOptions::VerbosityEnum& out, const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "verbose") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Verbose;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "extra") {
+ out = TestPreset::OutputOptions::VerbosityEnum::Extra;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalOutputVerbosityHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions::VerbosityEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetOutputVerbosityHelper);
+
+auto const TestPresetOptionalOutputHelper =
+ cmJSONOptionalHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::OutputOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("shortProgress"_s, &TestPreset::OutputOptions::ShortProgress,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("verbosity"_s, &TestPreset::OutputOptions::Verbosity,
+ TestPresetOptionalOutputVerbosityHelper, false)
+ .Bind("debug"_s, &TestPreset::OutputOptions::Debug,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("outputOnFailure"_s, &TestPreset::OutputOptions::OutputOnFailure,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("quiet"_s, &TestPreset::OutputOptions::Quiet,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("subprojectSummary"_s,
+ &TestPreset::OutputOptions::SubprojectSummary,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("maxPassedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxPassedTestOutputSize,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("maxFailedTestOutputSize"_s,
+ &TestPreset::OutputOptions::MaxFailedTestOutputSize,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("maxTestNameWidth"_s, &TestPreset::OutputOptions::MaxTestNameWidth,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false));
+
+auto const TestPresetOptionalFilterIncludeIndexObjectHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions::IndexOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("start"_s, &TestPreset::IncludeOptions::IndexOptions::Start,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("end"_s, &TestPreset::IncludeOptions::IndexOptions::End,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("stride"_s, &TestPreset::IncludeOptions::IndexOptions::Stride,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("specificTests"_s,
+ &TestPreset::IncludeOptions::IndexOptions::SpecificTests,
+ cmCMakePresetsGraphInternal::PresetVectorIntHelper, false));
+
+ReadFileResult TestPresetOptionalFilterIncludeIndexHelper(
+ cm::optional<TestPreset::IncludeOptions::IndexOptions>& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.emplace();
+ out->IndexFile = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isObject()) {
+ return TestPresetOptionalFilterIncludeIndexObjectHelper(out, value);
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalFilterIncludeHelper =
+ cmJSONOptionalHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::IncludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::IncludeOptions::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("label"_s, &TestPreset::IncludeOptions::Label,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("index"_s, &TestPreset::IncludeOptions::Index,
+ TestPresetOptionalFilterIncludeIndexHelper, false)
+ .Bind("useUnion"_s, &TestPreset::IncludeOptions::UseUnion,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false));
+
+auto const TestPresetOptionalFilterExcludeFixturesHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions::FixturesOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("any"_s, &TestPreset::ExcludeOptions::FixturesOptions::Any,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("setup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Setup,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("cleanup"_s, &TestPreset::ExcludeOptions::FixturesOptions::Cleanup,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false));
+
+auto const TestPresetOptionalFilterExcludeHelper =
+ cmJSONOptionalHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExcludeOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("name"_s, &TestPreset::ExcludeOptions::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("label"_s, &TestPreset::ExcludeOptions::Label,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("fixtures"_s, &TestPreset::ExcludeOptions::Fixtures,
+ TestPresetOptionalFilterExcludeFixturesHelper, false));
+
+ReadFileResult TestPresetExecutionShowOnlyHelper(
+ TestPreset::ExecutionOptions::ShowOnlyEnum& out, const Json::Value* value)
+{
+ if (!value || !value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "human") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::Human;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "json-v1") {
+ out = TestPreset::ExecutionOptions::ShowOnlyEnum::JsonV1;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionShowOnlyHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::ShowOnlyEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionShowOnlyHelper);
+
+ReadFileResult TestPresetExecutionModeHelper(
+ TestPreset::ExecutionOptions::RepeatOptions::ModeEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "until-fail") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilFail;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "until-pass") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::UntilPass;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "after-timeout") {
+ out = TestPreset::ExecutionOptions::RepeatOptions::ModeEnum::AfterTimeout;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionRepeatHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions::RepeatOptions,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_PRESET)
+ .Bind("mode"_s, &TestPreset::ExecutionOptions::RepeatOptions::Mode,
+ TestPresetExecutionModeHelper, true)
+ .Bind("count"_s, &TestPreset::ExecutionOptions::RepeatOptions::Count,
+ cmCMakePresetsGraphInternal::PresetIntHelper, true));
+
+ReadFileResult TestPresetExecutionNoTestsActionHelper(
+ TestPreset::ExecutionOptions::NoTestsActionEnum& out,
+ const Json::Value* value)
+{
+ if (!value) {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "error") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Error;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "ignore") {
+ out = TestPreset::ExecutionOptions::NoTestsActionEnum::Ignore;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const TestPresetOptionalExecutionNoTestsActionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions::NoTestsActionEnum,
+ ReadFileResult>(ReadFileResult::READ_OK,
+ TestPresetExecutionNoTestsActionHelper);
+
+auto const TestPresetExecutionHelper =
+ cmJSONOptionalHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::ExecutionOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("stopOnFailure"_s, &TestPreset::ExecutionOptions::StopOnFailure,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("enableFailover"_s, &TestPreset::ExecutionOptions::EnableFailover,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("jobs"_s, &TestPreset::ExecutionOptions::Jobs,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("resourceSpecFile"_s,
+ &TestPreset::ExecutionOptions::ResourceSpecFile,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("testLoad"_s, &TestPreset::ExecutionOptions::TestLoad,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("showOnly"_s, &TestPreset::ExecutionOptions::ShowOnly,
+ TestPresetOptionalExecutionShowOnlyHelper, false)
+ .Bind("repeat"_s, &TestPreset::ExecutionOptions::Repeat,
+ TestPresetOptionalExecutionRepeatHelper, false)
+ .Bind("interactiveDebugging"_s,
+ &TestPreset::ExecutionOptions::InteractiveDebugging,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("scheduleRandom"_s, &TestPreset::ExecutionOptions::ScheduleRandom,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout,
+ cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false)
+ .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction,
+ TestPresetOptionalExecutionNoTestsActionHelper, false));
+
+auto const TestPresetFilterHelper =
+ cmJSONOptionalHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK,
+ cmJSONObjectHelper<TestPreset::FilterOptions, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET)
+ .Bind("include"_s, &TestPreset::FilterOptions::Include,
+ TestPresetOptionalFilterIncludeHelper, false)
+ .Bind("exclude"_s, &TestPreset::FilterOptions::Exclude,
+ TestPresetOptionalFilterExcludeHelper, false));
+
+auto const TestPresetHelper =
+ cmJSONObjectHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &TestPreset::Name,
+ cmCMakePresetsGraphInternal::PresetStringHelper)
+ .Bind("inherits"_s, &TestPreset::Inherits,
+ cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper,
+ false)
+ .Bind("hidden"_s, &TestPreset::Hidden,
+ cmCMakePresetsGraphInternal::PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ cmCMakePresetsGraphInternal::VendorHelper(
+ ReadFileResult::INVALID_PRESET),
+ false)
+ .Bind("displayName"_s, &TestPreset::DisplayName,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("description"_s, &TestPreset::Description,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("environment"_s, &TestPreset::Environment,
+ cmCMakePresetsGraphInternal::EnvironmentMapHelper, false)
+ .Bind("configurePreset"_s, &TestPreset::ConfigurePreset,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("inheritConfigureEnvironment"_s,
+ &TestPreset::InheritConfigureEnvironment,
+ cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false)
+ .Bind("configuration"_s, &TestPreset::Configuration,
+ cmCMakePresetsGraphInternal::PresetStringHelper, false)
+ .Bind("overwriteConfigurationFile"_s,
+ &TestPreset::OverwriteConfigurationFile,
+ cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)
+ .Bind("output"_s, &TestPreset::Output, TestPresetOptionalOutputHelper,
+ false)
+ .Bind("filter"_s, &TestPreset::Filter, TestPresetFilterHelper, false)
+ .Bind("execution"_s, &TestPreset::Execution, TestPresetExecutionHelper,
+ false)
+ .Bind("condition"_s, &TestPreset::ConditionEvaluator,
+ cmCMakePresetsGraphInternal::PresetConditionHelper, false);
+}
+
+namespace cmCMakePresetsGraphInternal {
+cmCMakePresetsGraph::ReadFileResult TestPresetsHelper(
+ std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value)
+{
+ static auto const helper = cmJSONVectorHelper<TestPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS,
+ TestPresetHelper);
+
+ return helper(out, value);
+}
+}
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index e460031..1b11f20 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -22,17 +22,17 @@
extern "C" {
-void CCONV* cmGetClientData(void* info)
+static void CCONV* cmGetClientData(void* info)
{
return ((cmLoadedCommandInfo*)info)->ClientData;
}
-void CCONV cmSetClientData(void* info, void* cd)
+static void CCONV cmSetClientData(void* info, void* cd)
{
((cmLoadedCommandInfo*)info)->ClientData = cd;
}
-void CCONV cmSetError(void* info, const char* err)
+static void CCONV cmSetError(void* info, const char* err)
{
if (((cmLoadedCommandInfo*)info)->Error) {
free(((cmLoadedCommandInfo*)info)->Error);
@@ -40,30 +40,31 @@ void CCONV cmSetError(void* info, const char* err)
((cmLoadedCommandInfo*)info)->Error = strdup(err);
}
-unsigned int CCONV cmGetCacheMajorVersion(void* arg)
+static unsigned int CCONV cmGetCacheMajorVersion(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmState* state = mf->GetState();
return state->GetCacheMajorVersion();
}
-unsigned int CCONV cmGetCacheMinorVersion(void* arg)
+static unsigned int CCONV cmGetCacheMinorVersion(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmState* state = mf->GetState();
return state->GetCacheMinorVersion();
}
-unsigned int CCONV cmGetMajorVersion(void*)
+static unsigned int CCONV cmGetMajorVersion(void*)
{
return cmVersion::GetMajorVersion();
}
-unsigned int CCONV cmGetMinorVersion(void*)
+static unsigned int CCONV cmGetMinorVersion(void*)
{
return cmVersion::GetMinorVersion();
}
-void CCONV cmAddDefinition(void* arg, const char* name, const char* value)
+static void CCONV cmAddDefinition(void* arg, const char* name,
+ const char* value)
{
if (value) {
cmMakefile* mf = static_cast<cmMakefile*>(arg);
@@ -72,8 +73,9 @@ void CCONV cmAddDefinition(void* arg, const char* name, const char* 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)
+static void CCONV cmAddCacheDefinition(void* arg, const char* name,
+ const char* value, const char* doc,
+ int type)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
@@ -99,7 +101,7 @@ void CCONV cmAddCacheDefinition(void* arg, const char* name, const char* value,
}
}
-const char* CCONV cmGetProjectName(void* arg)
+static const char* CCONV cmGetProjectName(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
static std::string name;
@@ -107,63 +109,63 @@ const char* CCONV cmGetProjectName(void* arg)
return name.c_str();
}
-const char* CCONV cmGetHomeDirectory(void* arg)
+static const char* CCONV cmGetHomeDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetHomeDirectory().c_str();
}
-const char* CCONV cmGetHomeOutputDirectory(void* arg)
+static const char* CCONV cmGetHomeOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetHomeOutputDirectory().c_str();
}
-const char* CCONV cmGetStartDirectory(void* arg)
+static const char* CCONV cmGetStartDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetCurrentSourceDirectory().c_str();
}
-const char* CCONV cmGetStartOutputDirectory(void* arg)
+static const char* CCONV cmGetStartOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetCurrentBinaryDirectory().c_str();
}
-const char* CCONV cmGetCurrentDirectory(void* arg)
+static const char* CCONV cmGetCurrentDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetCurrentSourceDirectory().c_str();
}
-const char* CCONV cmGetCurrentOutputDirectory(void* arg)
+static const char* CCONV cmGetCurrentOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetCurrentBinaryDirectory().c_str();
}
-const char* CCONV cmGetDefinition(void* arg, const char* def)
+static const char* CCONV cmGetDefinition(void* arg, const char* def)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
return mf->GetDefinition(def).GetCStr();
}
-int CCONV cmIsOn(void* arg, const char* name)
+static int CCONV cmIsOn(void* arg, const char* name)
{
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)
+static int CCONV cmCommandExists(void* arg, const char* 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)
+static void CCONV cmAddDefineFlag(void* arg, const char* definition)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
mf->AddDefineFlag(definition);
}
-void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
- const char* d)
+static void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
+ const char* d)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmTarget* t = mf->FindLocalNonAliasTarget(tgt);
@@ -176,8 +178,8 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
t->InsertLinkDirectory(BT<std::string>(d, mf->GetBacktrace()));
}
-void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
- const char** srcs, int win32)
+static void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
+ const char** srcs, int win32)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::vector<std::string> srcs2;
@@ -191,10 +193,11 @@ void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
}
}
-void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
- const char* command, const char* arguments,
- int all, int numDepends, const char** depends,
- int, const char**)
+static 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.
@@ -220,17 +223,17 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
}
// Pass the call to the makefile instance.
- std::vector<std::string> no_byproducts;
- mf->AddUtilityCommand(utilityName, !all, nullptr, no_byproducts, depends2,
- commandLines,
- mf->GetPolicyStatus(cmPolicies::CMP0116));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetDepends(depends2);
+ cc->SetCommandLines(commandLines);
+ mf->AddUtilityCommand(utilityName, !all, std::move(cc));
}
-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)
+static 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.
@@ -264,15 +267,15 @@ void CCONV cmAddCustomCommand(void* arg, const char* source,
// Pass the call to the makefile instance.
const char* no_comment = nullptr;
mf->AddCustomCommandOldStyle(target, outputs2, depends2, source,
- commandLines, no_comment,
- mf->GetPolicyStatus(cmPolicies::CMP0116));
+ 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)
+static 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.
@@ -297,16 +300,18 @@ void CCONV cmAddCustomCommandToOutput(void* arg, const char* output,
}
// Pass the call to the makefile instance.
- const char* no_comment = nullptr;
- const char* no_working_dir = nullptr;
- mf->AddCustomCommandToOutput(output, depends2, main_dependency, commandLines,
- no_comment, no_working_dir,
- mf->GetPolicyStatus(cmPolicies::CMP0116));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(output);
+ cc->SetMainDependency(main_dependency);
+ cc->SetDepends(depends2);
+ cc->SetCommandLines(commandLines);
+ mf->AddCustomCommandToOutput(std::move(cc));
}
-void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
- const char* command, int numArgs,
- const char** args, int commandType)
+static 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);
@@ -338,13 +343,9 @@ void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
}
// Pass the call to the makefile instance.
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
- const char* no_comment = nullptr;
- const char* no_working_dir = nullptr;
- mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
- cctype, no_comment, no_working_dir,
- mf->GetPolicyStatus(cmPolicies::CMP0116));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCommandLines(commandLines);
+ mf->AddCustomCommandToTarget(target, cctype, std::move(cc));
}
static void addLinkLibrary(cmMakefile* mf, std::string const& target,
@@ -376,8 +377,8 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target,
t->AddLinkLibrary(*mf, lib, llt);
}
-void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt,
- const char* value, int libtype)
+static void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt,
+ const char* value, int libtype)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
@@ -394,8 +395,8 @@ void CCONV cmAddLinkLibraryForTarget(void* arg, const char* tgt,
}
}
-void CCONV cmAddLibrary(void* arg, const char* libname, int shared,
- int numSrcs, const char** srcs)
+static void CCONV cmAddLibrary(void* arg, const char* libname, int shared,
+ int numSrcs, const char** srcs)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::vector<std::string> srcs2;
@@ -409,8 +410,8 @@ void CCONV cmAddLibrary(void* arg, const char* libname, int shared,
srcs2);
}
-char CCONV* cmExpandVariablesInString(void* arg, const char* source,
- int escapeQuotes, int atOnly)
+static char CCONV* cmExpandVariablesInString(void* arg, const char* source,
+ int escapeQuotes, int atOnly)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::string barf = source;
@@ -419,8 +420,8 @@ char CCONV* cmExpandVariablesInString(void* arg, const char* source,
return strdup(result.c_str());
}
-int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
- const char** args)
+static int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
+ const char** args)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
@@ -436,10 +437,10 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
return mf->ExecuteCommand(lff, status);
}
-void CCONV cmExpandSourceListArguments(void* arg, int numArgs,
- const char** args, int* resArgc,
- char*** resArgv,
- unsigned int startArgumentIndex)
+static void CCONV cmExpandSourceListArguments(void* arg, int numArgs,
+ const char** args, int* resArgc,
+ char*** resArgv,
+ unsigned int startArgumentIndex)
{
(void)arg;
(void)startArgumentIndex;
@@ -460,7 +461,7 @@ void CCONV cmExpandSourceListArguments(void* arg, int numArgs,
*resArgv = resargv;
}
-void CCONV cmFreeArguments(int argc, char** argv)
+static void CCONV cmFreeArguments(int argc, char** argv)
{
int i;
for (i = 0; i < argc; ++i) {
@@ -469,7 +470,7 @@ void CCONV cmFreeArguments(int argc, char** argv)
free(argv);
}
-int CCONV cmGetTotalArgumentSize(int argc, char** argv)
+static int CCONV cmGetTotalArgumentSize(int argc, char** argv)
{
int i;
int result = 0;
@@ -497,19 +498,19 @@ struct cmCPluginAPISourceFile
// the CPluginAPI proxy source file.
using cmCPluginAPISourceFileMap =
std::map<cmSourceFile*, std::unique_ptr<cmCPluginAPISourceFile>>;
-cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
+static cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
-void* CCONV cmCreateSourceFile(void)
+static void* CCONV cmCreateSourceFile()
{
return new cmCPluginAPISourceFile;
}
-void* CCONV cmCreateNewSourceFile(void*)
+static void* CCONV cmCreateNewSourceFile(void*)
{
return new cmCPluginAPISourceFile;
}
-void CCONV cmDestroySourceFile(void* arg)
+static void CCONV cmDestroySourceFile(void* arg)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
// Only delete if it was created by cmCreateSourceFile or
@@ -519,7 +520,7 @@ void CCONV cmDestroySourceFile(void* arg)
}
}
-void CCONV* cmGetSource(void* arg, const char* name)
+static void CCONV* cmGetSource(void* arg, const char* name)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
if (cmSourceFile* rsf = mf->GetSource(name)) {
@@ -543,7 +544,7 @@ void CCONV* cmGetSource(void* arg, const char* name)
return nullptr;
}
-void* CCONV cmAddSource(void* arg, void* arg2)
+static void* CCONV cmAddSource(void* arg, void* arg2)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2);
@@ -576,19 +577,19 @@ void* CCONV cmAddSource(void* arg, void* arg2)
return value;
}
-const char* CCONV cmSourceFileGetSourceName(void* arg)
+static const char* CCONV cmSourceFileGetSourceName(void* arg)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
return sf->SourceName.c_str();
}
-const char* CCONV cmSourceFileGetFullPath(void* arg)
+static 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)
+static const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
@@ -600,7 +601,7 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop)
return sf->Properties.GetPropertyValue(prop).GetCStr();
}
-int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
+static int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
@@ -609,8 +610,8 @@ int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
return cmIsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0;
}
-void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
- const char* value)
+static void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
+ const char* value)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
@@ -623,7 +624,7 @@ void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
}
}
-void CCONV cmSourceFileAddDepend(void* arg, const char* depend)
+static void CCONV cmSourceFileAddDepend(void* arg, const char* depend)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
@@ -633,11 +634,11 @@ void CCONV cmSourceFileAddDepend(void* arg, const char* depend)
}
}
-void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
- int numSourceExtensions,
- const char** sourceExtensions,
- int numHeaderExtensions,
- const char** headerExtensions)
+static void CCONV cmSourceFileSetName(void* arg, const char* name,
+ const char* dir, int numSourceExtensions,
+ const char** sourceExtensions,
+ int numHeaderExtensions,
+ const char** headerExtensions)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (sf->RealSourceFile) {
@@ -718,8 +719,9 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
cmSystemTools::Error(e.str());
}
-void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
- const char* ext, int headerFileOnly)
+static 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) {
@@ -743,48 +745,48 @@ void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
sf->SourceExtension = ext;
}
-char* CCONV cmGetFilenameWithoutExtension(const char* name)
+static char* CCONV cmGetFilenameWithoutExtension(const char* name)
{
std::string sres = cmSystemTools::GetFilenameWithoutExtension(name);
return strdup(sres.c_str());
}
-char* CCONV cmGetFilenamePath(const char* name)
+static char* CCONV cmGetFilenamePath(const char* name)
{
std::string sres = cmSystemTools::GetFilenamePath(name);
return strdup(sres.c_str());
}
-char* CCONV cmCapitalized(const char* name)
+static char* CCONV cmCapitalized(const char* name)
{
std::string sres = cmSystemTools::Capitalized(name);
return strdup(sres.c_str());
}
-void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2)
+static void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2)
{
cmSystemTools::CopyFileIfDifferent(name1, name2);
}
-void CCONV cmRemoveFile(const char* name)
+static void CCONV cmRemoveFile(const char* name)
{
cmSystemTools::RemoveFile(name);
}
-void CCONV cmDisplayStatus(void* arg, const char* message)
+static void CCONV cmDisplayStatus(void* arg, const char* message)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
mf->DisplayStatus(message, -1);
}
-void CCONV cmFree(void* data)
+static void CCONV cmFree(void* data)
{
free(data);
}
-void CCONV DefineSourceFileProperty(void* arg, const char* name,
- const char* briefDocs,
- const char* longDocs, int chained)
+static void CCONV DefineSourceFileProperty(void* arg, const char* name,
+ const char* briefDocs,
+ const char* longDocs, int chained)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE,
@@ -794,7 +796,7 @@ void CCONV DefineSourceFileProperty(void* arg, const char* name,
} // close the extern "C" scope
-cmCAPI cmStaticCAPI = {
+static cmCAPI cmStaticCAPI = {
cmGetClientData,
cmGetTotalArgumentSize,
cmFreeArguments,
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index dfd2b6c..a1e920e 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -38,7 +38,7 @@
# include <unistd.h> // IWYU pragma: keep
#endif
-#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsGraph.h"
#include "cmCTestBuildAndTestHandler.h"
#include "cmCTestBuildHandler.h"
#include "cmCTestConfigureHandler.h"
@@ -227,8 +227,8 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
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());
+ snprintf(buf, sizeof(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
@@ -543,9 +543,9 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
this->Impl->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,
- lctime->tm_min);
+ snprintf(datestring, sizeof(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;
cmsys::ofstream ofs(tagfile.c_str());
if (ofs) {
@@ -2327,12 +2327,12 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
{
const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
- cmCMakePresetsFile settingsFile;
+ cmCMakePresetsGraph settingsFile;
auto result = settingsFile.ReadProjectPresets(workingDirectory);
- if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
- cmSystemTools::Error(cmStrCat("Could not read presets from ",
- workingDirectory, ": ",
- cmCMakePresetsFile::ResultToString(result)));
+ if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
+ cmSystemTools::Error(
+ cmStrCat("Could not read presets from ", workingDirectory, ": ",
+ cmCMakePresetsGraph::ResultToString(result)));
return false;
}
@@ -2422,15 +2422,15 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Output->Verbosity) {
const auto& verbosity = *expandedPreset->Output->Verbosity;
switch (verbosity) {
- case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ case cmCMakePresetsGraph::TestPreset::OutputOptions::VerbosityEnum::
Extra:
this->Impl->ExtraVerbose = true;
CM_FALLTHROUGH;
- case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ case cmCMakePresetsGraph::TestPreset::OutputOptions::VerbosityEnum::
Verbose:
this->Impl->Verbose = true;
break;
- case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
+ case cmCMakePresetsGraph::TestPreset::OutputOptions::VerbosityEnum::
Default:
default:
// leave default settings
@@ -2548,13 +2548,13 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
this->Impl->ShowOnly = true;
switch (*expandedPreset->Execution->ShowOnly) {
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::ShowOnlyEnum::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::ShowOnlyEnum::
JsonV1:
this->Impl->Quiet = true;
this->Impl->OutputAsJson = true;
this->Impl->OutputAsJsonVersion = 1;
break;
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::ShowOnlyEnum::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::ShowOnlyEnum::
Human:
// intentional fallthrough (human is the default)
default:
@@ -2565,15 +2565,15 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Execution->Repeat) {
this->Impl->RepeatCount = expandedPreset->Execution->Repeat->Count;
switch (expandedPreset->Execution->Repeat->Mode) {
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::RepeatOptions::
ModeEnum::UntilFail:
this->Impl->RepeatMode = cmCTest::Repeat::UntilFail;
break;
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::RepeatOptions::
ModeEnum::UntilPass:
this->Impl->RepeatMode = cmCTest::Repeat::UntilPass;
break;
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::RepeatOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::RepeatOptions::
ModeEnum::AfterTimeout:
this->Impl->RepeatMode = cmCTest::Repeat::AfterTimeout;
break;
@@ -2599,15 +2599,15 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
if (expandedPreset->Execution->NoTestsAction) {
switch (*expandedPreset->Execution->NoTestsAction) {
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::
NoTestsActionEnum::Error:
this->Impl->NoTestsMode = cmCTest::NoTests::Error;
break;
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::
NoTestsActionEnum::Ignore:
this->Impl->NoTestsMode = cmCTest::NoTests::Ignore;
break;
- case cmCMakePresetsFile::TestPreset::ExecutionOptions::
+ case cmCMakePresetsGraph::TestPreset::ExecutionOptions::
NoTestsActionEnum::Default:
break;
default:
@@ -2967,8 +2967,9 @@ void cmCTest::SetStopTime(std::string const& time_str)
tzone_offset *= 100;
char buf[1024];
- sprintf(buf, "%d%02d%02d %s %+05i", lctime->tm_year + 1900,
- lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(), tzone_offset);
+ snprintf(buf, sizeof(buf), "%d%02d%02d %s %+05i", lctime->tm_year + 1900,
+ lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(),
+ tzone_offset);
time_t stop_time = curl_getdate(buf, &current_time);
if (stop_time == -1) {
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 8d5ce7e..129ef4b 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -101,7 +101,8 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags(
}
void cmCommonTargetGenerator::AppendFortranPreprocessFlags(
- std::string& flags, cmSourceFile const& source)
+ std::string& flags, cmSourceFile const& source,
+ PreprocessFlagsRequired requires_pp)
{
const std::string srcpp = source.GetSafeProperty("Fortran_PREPROCESS");
cmOutputConverter::FortranPreprocess preprocess =
@@ -114,7 +115,9 @@ void cmCommonTargetGenerator::AppendFortranPreprocessFlags(
const char* var = nullptr;
switch (preprocess) {
case cmOutputConverter::FortranPreprocess::Needed:
- var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON";
+ if (requires_pp == PreprocessFlagsRequired::YES) {
+ var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON";
+ }
break;
case cmOutputConverter::FortranPreprocess::NotNeeded:
var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF";
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index baa36c9..5aba1c6 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -46,8 +46,14 @@ protected:
void AppendFortranFormatFlags(std::string& flags,
cmSourceFile const& source);
- void AppendFortranPreprocessFlags(std::string& flags,
- cmSourceFile const& source);
+ enum class PreprocessFlagsRequired
+ {
+ YES,
+ NO
+ };
+ void AppendFortranPreprocessFlags(
+ std::string& flags, cmSourceFile const& source,
+ PreprocessFlagsRequired requires_pp = PreprocessFlagsRequired::YES);
virtual void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) = 0;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 831a81f..2ff91fe 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -722,7 +722,7 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
this->AddFrameworkItem(item.Value);
} else if (cmSystemTools::FileIsDirectory(item.Value)) {
// This is a directory.
- this->DropDirectoryItem(item.Value);
+ this->DropDirectoryItem(item);
} else {
// Use the full path given to the library file.
this->Depends.push_back(item.Value);
@@ -1349,16 +1349,17 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
}
}
-void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
+void cmComputeLinkInformation::DropDirectoryItem(BT<std::string> const& item)
{
// A full path to a directory was found as a link item. Warn the
// user.
- std::ostringstream e;
- e << "WARNING: Target \"" << this->Target->GetName()
- << "\" requests linking to directory \"" << item << "\". "
- << "Targets may link only to libraries. "
- << "CMake is dropping the item.";
- cmSystemTools::Message(e.str());
+ this->CMakeInstance->IssueMessage(
+ MessageType::WARNING,
+ cmStrCat(
+ "Target \"", this->Target->GetName(),
+ "\" requests linking to directory \"", item.Value,
+ "\". Targets may link only to libraries. CMake is dropping the item."),
+ item.Backtrace);
}
void cmComputeLinkInformation::ComputeFrameworkInfo()
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 90a699e..0315540 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -187,7 +187,7 @@ private:
bool CheckImplicitDirItem(std::string const& item);
void AddUserItem(BT<std::string> const& item, bool pathNotKnown);
void AddFrameworkItem(std::string const& item);
- void DropDirectoryItem(std::string const& item);
+ void DropDirectoryItem(BT<std::string> const& item);
bool CheckSharedLibNoSOName(std::string const& item);
void AddSharedLibNoSOName(std::string const& item);
void HandleBadFullItem(std::string const& item, std::string const& file);
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 971c86e..84fa897 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -699,7 +699,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
/* Use a random file name to avoid rapid creation and deletion
of the same executable name (some filesystems fail on that). */
- sprintf(targetNameBuf, "cmTC_%05x", cmSystemTools::RandomSeed() & 0xFFFFF);
+ snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
+ cmSystemTools::RandomSeed() & 0xFFFFF);
targetName = targetNameBuf;
if (!targets.empty()) {
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index ec60ff7..68c65bb 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -2,32 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCustomCommand.h"
+#include <cassert>
#include <utility>
#include <cmext/algorithm>
-cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs,
- std::vector<std::string> byproducts,
- std::vector<std::string> depends,
- cmCustomCommandLines commandLines,
- cmListFileBacktrace lfbt, const char* comment,
- const char* workingDirectory,
- bool stdPipesUTF8)
- : Outputs(std::move(outputs))
- , Byproducts(std::move(byproducts))
- , Depends(std::move(depends))
- , CommandLines(std::move(commandLines))
- , Backtrace(std::move(lfbt))
- , Comment(comment ? comment : "")
- , WorkingDirectory(workingDirectory ? workingDirectory : "")
- , HaveComment(comment != nullptr)
- , StdPipesUTF8(stdPipesUTF8)
+const std::vector<std::string>& cmCustomCommand::GetOutputs() const
{
+ return this->Outputs;
}
-const std::vector<std::string>& cmCustomCommand::GetOutputs() const
+void cmCustomCommand::SetOutputs(std::vector<std::string> outputs)
{
- return this->Outputs;
+ this->Outputs = std::move(outputs);
+}
+
+void cmCustomCommand::SetOutputs(std::string output)
+{
+ this->Outputs = { std::move(output) };
}
const std::vector<std::string>& cmCustomCommand::GetByproducts() const
@@ -35,22 +27,66 @@ const std::vector<std::string>& cmCustomCommand::GetByproducts() const
return this->Byproducts;
}
+void cmCustomCommand::SetByproducts(std::vector<std::string> byproducts)
+{
+ this->Byproducts = std::move(byproducts);
+}
+
const std::vector<std::string>& cmCustomCommand::GetDepends() const
{
return this->Depends;
}
+void cmCustomCommand::SetDepends(std::vector<std::string> depends)
+{
+ if (this->HasMainDependency_) {
+ depends.insert(depends.begin(), std::move(this->Depends[0]));
+ }
+
+ Depends = std::move(depends);
+}
+
+const std::string& cmCustomCommand::GetMainDependency() const
+{
+ assert(this->HasMainDependency_);
+ return this->Depends[0];
+}
+
+void cmCustomCommand::SetMainDependency(std::string main_dependency)
+{
+ if (this->HasMainDependency_) {
+ assert(!main_dependency.empty());
+ this->Depends[0] = std::move(main_dependency);
+ } else if (main_dependency.empty()) {
+ // Do nothing.
+ } else {
+ this->Depends.insert(this->Depends.begin(), std::move(main_dependency));
+ this->HasMainDependency_ = true;
+ }
+}
+
const cmCustomCommandLines& cmCustomCommand::GetCommandLines() const
{
return this->CommandLines;
}
+void cmCustomCommand::SetCommandLines(cmCustomCommandLines commandLines)
+{
+ this->CommandLines = std::move(commandLines);
+}
+
const char* cmCustomCommand::GetComment() const
{
const char* no_comment = nullptr;
return this->HaveComment ? this->Comment.c_str() : no_comment;
}
+void cmCustomCommand::SetComment(const char* comment)
+{
+ this->Comment = comment ? comment : "";
+ this->HaveComment = (comment != nullptr);
+}
+
void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
{
cm::append(this->CommandLines, commandLines);
@@ -86,6 +122,11 @@ cmListFileBacktrace const& cmCustomCommand::GetBacktrace() const
return this->Backtrace;
}
+void cmCustomCommand::SetBacktrace(cmListFileBacktrace lfbt)
+{
+ this->Backtrace = std::move(lfbt);
+}
+
cmImplicitDependsList const& cmCustomCommand::GetImplicitDepends() const
{
return this->ImplicitDepends;
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 5cbd3d1..5533847 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -25,22 +25,22 @@ class cmImplicitDependsList
class cmCustomCommand
{
public:
- /** Main constructor specifies all information for the command. */
- cmCustomCommand(std::vector<std::string> outputs,
- std::vector<std::string> byproducts,
- std::vector<std::string> depends,
- cmCustomCommandLines commandLines, cmListFileBacktrace lfbt,
- const char* comment, const char* workingDirectory,
- bool stdPipesUTF8);
-
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
+ void SetOutputs(std::vector<std::string> outputs);
+ void SetOutputs(std::string output);
/** Get the extra files produced by the command. */
const std::vector<std::string>& GetByproducts() const;
+ void SetByproducts(std::vector<std::string> byproducts);
/** Get the vector that holds the list of dependencies. */
const std::vector<std::string>& GetDepends() const;
+ void SetDepends(std::vector<std::string> depends);
+
+ bool HasMainDependency() const { return this->HasMainDependency_; }
+ const std::string& GetMainDependency() const;
+ void SetMainDependency(std::string main_dependency);
/** Get the working directory. */
std::string const& GetWorkingDirectory() const
@@ -48,14 +48,25 @@ public:
return this->WorkingDirectory;
}
+ void SetWorkingDirectory(const char* workingDirectory)
+ {
+ this->WorkingDirectory = (workingDirectory ? workingDirectory : "");
+ }
+
/** Get the list of command lines. */
const cmCustomCommandLines& GetCommandLines() const;
+ void SetCommandLines(cmCustomCommandLines commandLines);
/** Get the comment string for the command. */
const char* GetComment() const;
+ void SetComment(const char* comment);
/** Get a value indicating if the command uses UTF-8 output pipes. */
bool GetStdPipesUTF8() const { return this->StdPipesUTF8; }
+ void SetStdPipesUTF8(bool stdPipesUTF8)
+ {
+ this->StdPipesUTF8 = stdPipesUTF8;
+ }
/** Append to the list of command lines. */
void AppendCommands(const cmCustomCommandLines& commandLines);
@@ -74,6 +85,7 @@ public:
/** Backtrace of the command that created this custom command. */
cmListFileBacktrace const& GetBacktrace() const;
+ void SetBacktrace(cmListFileBacktrace lfbt);
void SetImplicitDepends(cmImplicitDependsList const&);
void AppendImplicitDepends(cmImplicitDependsList const&);
@@ -122,5 +134,6 @@ private:
bool UsesTerminal = false;
bool CommandExpandLists = false;
bool StdPipesUTF8 = false;
+ bool HasMainDependency_ = false;
cmPolicies::PolicyStatus CMP0116Status = cmPolicies::WARN;
};
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index fd0a63c..41d4442 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -346,7 +346,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
return this->CommandLines[c][0];
}
-std::string escapeForShellOldStyle(const std::string& str)
+static std::string escapeForShellOldStyle(const std::string& str)
{
std::string result;
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index 4e2d9b0..7a2f34f 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -2,9 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDefinePropertyCommand.h"
+#include <algorithm>
+#include <iterator>
+
+#include <cmext/string_view>
+
+#include "cmArgumentParser.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -44,37 +51,23 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
// Parse remaining arguments.
bool inherited = false;
std::string PropertyName;
- std::string BriefDocs;
- std::string FullDocs;
- enum Doing
- {
- DoingNone,
- DoingProperty,
- DoingBrief,
- DoingFull
- };
- Doing doing = DoingNone;
- for (unsigned int i = 1; i < args.size(); ++i) {
- if (args[i] == "PROPERTY") {
- doing = DoingProperty;
- } else if (args[i] == "BRIEF_DOCS") {
- doing = DoingBrief;
- } else if (args[i] == "FULL_DOCS") {
- doing = DoingFull;
- } else if (args[i] == "INHERITED") {
- doing = DoingNone;
- inherited = true;
- } else if (doing == DoingProperty) {
- doing = DoingNone;
- PropertyName = args[i];
- } else if (doing == DoingBrief) {
- BriefDocs += args[i];
- } else if (doing == DoingFull) {
- FullDocs += args[i];
- } else {
- status.SetError(cmStrCat("given invalid argument \"", args[i], "\"."));
- return false;
- }
+ std::vector<std::string> BriefDocs;
+ std::vector<std::string> FullDocs;
+ std::string initializeFromVariable;
+
+ cmArgumentParser<void> parser;
+ parser.Bind("PROPERTY"_s, PropertyName);
+ parser.Bind("BRIEF_DOCS"_s, BriefDocs);
+ parser.Bind("FULL_DOCS"_s, FullDocs);
+ parser.Bind("INHERITED"_s, inherited);
+ parser.Bind("INITIALIZE_FROM_VARIABLE"_s, initializeFromVariable);
+ std::vector<std::string> invalidArgs;
+
+ parser.Parse(cmMakeRange(args).advance(1), &invalidArgs);
+ if (!invalidArgs.empty()) {
+ status.SetError(
+ cmStrCat("given invalid argument \"", invalidArgs.front(), "\"."));
+ return false;
}
// Make sure a property name was found.
@@ -83,19 +76,47 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
return false;
}
- // Make sure documentation was given.
- if (BriefDocs.empty()) {
- status.SetError("not given a BRIEF_DOCS <brief-doc> argument.");
- return false;
+ if (!initializeFromVariable.empty()) {
+ // Make sure property scope is TARGET.
+ if (scope != cmProperty::TARGET) {
+ status.SetError(
+ "Scope must be TARGET if INITIALIZE_FROM_VARIABLE is specified");
+ return false;
+ }
+
+ // Make sure the variable has the property name as a suffix.
+ if (!cmHasSuffix(initializeFromVariable, PropertyName)) {
+ status.SetError(cmStrCat("Variable name \"", initializeFromVariable,
+ "\" does not end with property name \"",
+ PropertyName, "\""));
+ return false;
+ }
+ if (initializeFromVariable == PropertyName) {
+ status.SetError(cmStrCat(
+ "Variable name must have a non-empty prefix before property name \"",
+ PropertyName, "\""));
+ return false;
+ }
}
- if (FullDocs.empty()) {
- status.SetError("not given a FULL_DOCS <full-doc> argument.");
+
+ // Make sure the variable is not reserved.
+ static constexpr const char* reservedPrefixes[] = {
+ "CMAKE_",
+ "_CMAKE_",
+ };
+ if (std::any_of(std::begin(reservedPrefixes), std::end(reservedPrefixes),
+ [&initializeFromVariable](const char* prefix) {
+ return cmHasPrefix(initializeFromVariable, prefix);
+ })) {
+ status.SetError(
+ cmStrCat("variable name \"", initializeFromVariable, "\" is reserved"));
return false;
}
// Actually define the property.
status.GetMakefile().GetState()->DefineProperty(
- PropertyName, scope, BriefDocs, FullDocs, inherited);
+ PropertyName, scope, cmJoin(BriefDocs, ""), cmJoin(FullDocs, ""),
+ inherited, initializeFromVariable);
return true;
}
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx
index bf599ff..0cc4946 100644
--- a/Source/cmDependsCompiler.cxx
+++ b/Source/cmDependsCompiler.cxx
@@ -4,6 +4,7 @@
#include "cmDependsCompiler.h"
#include <algorithm>
+#include <iterator>
#include <map>
#include <memory>
#include <string>
@@ -111,9 +112,13 @@ bool cmDependsCompiler::CheckDependencies(
// copy depends for each target, except first one, which can be
// moved
for (auto index = entry.rules.size() - 1; index > 0; --index) {
- dependencies[entry.rules[index]] = depends;
+ auto& rule_deps = dependencies[entry.rules[index]];
+ rule_deps.insert(rule_deps.end(), depends.cbegin(),
+ depends.cend());
}
- dependencies[entry.rules.front()] = std::move(depends);
+ auto& rule_deps = dependencies[entry.rules.front()];
+ std::move(depends.cbegin(), depends.cend(),
+ std::back_inserter(rule_deps));
}
} else {
if (format == "msvc"_s) {
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 1678ce8..66f1733 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -26,17 +26,14 @@ template <size_t s>
struct cmELFByteSwapSize
{
};
-void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/)
-{
-}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
+static void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
{
char one_byte;
one_byte = data[0];
data[0] = data[1];
data[1] = one_byte;
}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
+static void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
{
char one_byte;
one_byte = data[0];
@@ -46,7 +43,7 @@ void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
data[1] = data[2];
data[2] = one_byte;
}
-void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
+static void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
{
char one_byte;
one_byte = data[0];
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 51fb219..e069b77 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -114,7 +114,7 @@ bool cmExecProgramCommand(std::vector<std::string> const& args,
if (!return_variable.empty()) {
char buffer[100];
- sprintf(buffer, "%d", retVal);
+ snprintf(buffer, sizeof(buffer), "%d", retVal);
status.GetMakefile().AddDefinition(return_variable, buffer);
}
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index ffcc415..3b990cc 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -318,7 +318,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
case cmsysProcess_State_Exited: {
int v = cmsysProcess_GetExitValue(cp);
char buf[16];
- sprintf(buf, "%d", v);
+ snprintf(buf, sizeof(buf), "%d", v);
status.GetMakefile().AddDefinition(arguments.ResultVariable, buf);
} break;
case cmsysProcess_State_Exception:
@@ -346,7 +346,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
int exitCode =
cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i));
char buf[16];
- sprintf(buf, "%d", exitCode);
+ snprintf(buf, sizeof(buf), "%d", exitCode);
res.emplace_back(buf);
} break;
case kwsysProcess_StateByIndex_Exception:
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 3641cb2..bcd8c64 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -106,7 +106,8 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
std::string sharedLibs;
std::string ldlibs;
cmLinkInterfaceLibraries const* linkIFace =
- target->GetLinkInterfaceLibraries(config, target, false);
+ target->GetLinkInterfaceLibraries(
+ config, target, cmGeneratorTarget::LinkInterfaceFor::Link);
for (cmLinkItem const& item : linkIFace->Libraries) {
cmGeneratorTarget const* gt = item.Target;
std::string const& lib = item.AsStr();
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index aa968dc..a47f1e5 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -11,12 +11,15 @@
#include <cmext/algorithm>
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -135,6 +138,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gte, properties);
this->GenerateInterfaceProperties(gte, os, properties);
+
+ this->GenerateTargetFileSets(gte, os);
}
// Generate import file content for each configuration.
@@ -356,3 +361,17 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+std::string cmExportBuildFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetDirectoryEntries(), ";"));
+}
+
+std::string cmExportBuildFileGenerator::GetFileSetFiles(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetFileEntries(), ";"));
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 244f526..a7985c7 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -15,9 +15,11 @@
#include "cmStateTypes.h"
class cmExportSet;
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLocalGenerator;
+class cmTargetExport;
/** \class cmExportBuildFileGenerator
* \brief Generate a file exporting targets from a build tree.
@@ -76,6 +78,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+ std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 8b0f64e..b46b933 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h"
+#include <array>
#include <cassert>
#include <cstring>
#include <sstream>
@@ -12,6 +13,7 @@
#include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -174,18 +176,24 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
if (!target->IsLinkable()) {
return false;
}
- cmValue 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;
+ static const std::array<std::string, 3> linkIfaceProps = {
+ { "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT",
+ "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" }
+ };
+ bool hadINTERFACE_LINK_LIBRARIES = false;
+ for (std::string const& linkIfaceProp : linkIfaceProps) {
+ if (cmValue input = target->GetProperty(linkIfaceProp)) {
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(*input, preprocessRule);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(
+ prepro, target, missingTargets, ReplaceFreeTargets);
+ properties[linkIfaceProp] = prepro;
+ hadINTERFACE_LINK_LIBRARIES = true;
+ }
}
}
- return false;
+ return hadINTERFACE_LINK_LIBRARIES;
}
static bool isSubDirectory(std::string const& a, std::string const& b)
@@ -495,8 +503,9 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
properties, missingTargets);
}
-void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
- std::set<std::string>& ifaceProperties)
+static void getPropertyContents(cmGeneratorTarget const* tgt,
+ const std::string& prop,
+ std::set<std::string>& ifaceProperties)
{
cmValue p = tgt->GetProperty(prop);
if (!p) {
@@ -506,9 +515,9 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
ifaceProperties.insert(content.begin(), content.end());
}
-void getCompatibleInterfaceProperties(cmGeneratorTarget const* target,
- std::set<std::string>& ifaceProperties,
- const std::string& config)
+static void getCompatibleInterfaceProperties(
+ cmGeneratorTarget const* target, std::set<std::string>& ifaceProperties,
+ const std::string& config)
{
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// object libraries have no link information, so nothing to compute
@@ -925,13 +934,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.20 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.21 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6...3.20)\n";
+ << "cmake_policy(VERSION 2.6...3.21)\n";
/* clang-format on */
}
@@ -1073,6 +1082,12 @@ void cmExportFileGenerator::GenerateImportTargetCode(
os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
<< cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
}
+
+ if (target->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
+ os << "set_property(TARGET " << targetName
+ << " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
+ }
+
os << "\n";
}
@@ -1250,3 +1265,38 @@ bool cmExportFileGenerator::PopulateExportProperties(
}
return true;
}
+
+void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
+ std::ostream& os,
+ cmTargetExport* te)
+{
+ auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
+ if (!interfaceFileSets.empty()) {
+ std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
+ os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
+ " target_sources("
+ << targetName << "\n";
+
+ for (auto const& name : interfaceFileSets) {
+ auto* fileSet = gte->Target->GetFileSet(name);
+ if (!fileSet) {
+ gte->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("File set \"", name,
+ "\" is listed in interface file sets of ", gte->GetName(),
+ " but has not been created"));
+ return;
+ }
+
+ os << " INTERFACE"
+ << "\n FILE_SET " << cmOutputConverter::EscapeForCMake(name)
+ << "\n TYPE "
+ << cmOutputConverter::EscapeForCMake(fileSet->GetType())
+ << "\n BASE_DIRS "
+ << this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
+ << this->GetFileSetFiles(gte, fileSet, te) << "\n";
+ }
+
+ os << " )\nendif()\n\n";
+ }
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 29a6a98..d50f7e8 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -15,6 +15,7 @@
#include "cmVersion.h"
#include "cmVersionConfig.h"
+class cmFileSet;
class cmGeneratorTarget;
class cmTargetExport;
@@ -186,6 +187,16 @@ protected:
ImportPropertyMap& properties,
std::string& errorMessage);
+ void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
+ cmTargetExport* te = nullptr);
+
+ virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
+ cmFileSet* fileSet,
+ cmTargetExport* te) = 0;
+ virtual std::string GetFileSetFiles(cmGeneratorTarget* gte,
+ cmFileSet* fileSet,
+ cmTargetExport* te) = 0;
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 4a3c565..f232440 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -2,19 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
+#include <algorithm>
#include <memory>
#include <sstream>
#include <utility>
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -148,6 +152,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateCompatibleInterfaceProperties(gt, properties);
this->GenerateInterfaceProperties(gt, os, properties);
+
+ this->GenerateTargetFileSets(gt, os, te);
}
if (require3_1_0) {
@@ -535,3 +541,102 @@ std::string cmExportInstallFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+namespace {
+bool EntryIsContextSensitive(
+ const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
+{
+ return cge->GetHadContextSensitiveCondition();
+}
+}
+
+std::string cmExportInstallFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+{
+ std::vector<std::string> resultVector;
+
+ auto configs =
+ gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
+ cmGeneratorExpression ge;
+ auto cge = ge.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
+
+ for (auto const& config : configs) {
+ auto dest = cmStrCat("${_IMPORT_PREFIX}/",
+ cmOutputConverter::EscapeForCMake(
+ cge->Evaluate(gte->LocalGenerator, config, gte),
+ cmOutputConverter::WrapQuotes::NoWrap));
+
+ if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
+ resultVector.push_back(
+ cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
+ } else {
+ resultVector.push_back(cmStrCat('"', dest, '"'));
+ break;
+ }
+ }
+
+ return cmJoin(resultVector, " ");
+}
+
+std::string cmExportInstallFileGenerator::GetFileSetFiles(
+ cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te)
+{
+ std::vector<std::string> resultVector;
+
+ auto configs =
+ gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
+ auto fileEntries = fileSet->CompileFileEntries();
+ auto directoryEntries = fileSet->CompileDirectoryEntries();
+
+ cmGeneratorExpression destGe;
+ auto destCge =
+ destGe.Parse(te->FileSetGenerators.at(fileSet)->GetDestination());
+
+ for (auto const& config : configs) {
+ auto directories = fileSet->EvaluateDirectoryEntries(
+ directoryEntries, gte->LocalGenerator, config, gte);
+
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ fileSet->EvaluateFileEntry(directories, files, entry,
+ gte->LocalGenerator, config, gte);
+ }
+ auto dest = cmStrCat("${_IMPORT_PREFIX}/",
+ cmOutputConverter::EscapeForCMake(
+ destCge->Evaluate(gte->LocalGenerator, config, gte),
+ cmOutputConverter::WrapQuotes::NoWrap),
+ '/');
+
+ bool const contextSensitive = destCge->GetHadContextSensitiveCondition() ||
+ std::any_of(directoryEntries.begin(), directoryEntries.end(),
+ EntryIsContextSensitive) ||
+ std::any_of(fileEntries.begin(), fileEntries.end(),
+ EntryIsContextSensitive);
+
+ for (auto const& it : files) {
+ auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
+ for (auto const& filename : it.second) {
+ auto relFile =
+ cmStrCat(prefix, cmSystemTools::GetFilenameName(filename));
+ auto escapedFile =
+ cmStrCat(dest,
+ cmOutputConverter::EscapeForCMake(
+ relFile, cmOutputConverter::WrapQuotes::NoWrap));
+ if (contextSensitive && configs.size() != 1) {
+ resultVector.push_back(
+ cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
+ } else {
+ resultVector.push_back(cmStrCat('"', escapedFile, '"'));
+ }
+ }
+ }
+
+ if (!(contextSensitive && configs.size() != 1)) {
+ break;
+ }
+ }
+
+ return cmJoin(resultVector, " ");
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 5cec2e0..9374c6b 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -14,6 +14,7 @@
#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
@@ -97,6 +98,11 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+ std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cbe3c4d..e98aa05 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -7,17 +7,22 @@
#include <cm/memory>
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmValue.h"
+class cmTargetExport;
+
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
cmMakefile* mf, std::set<std::string> const& langs)
@@ -102,10 +107,18 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
const cmGeneratorTarget* target, ImportPropertyMap& properties,
std::set<cmGeneratorTarget const*>& emitted)
{
+ // Look through all non-special properties.
std::vector<std::string> props = target->GetPropertyKeys();
+ // Include special properties that might be relevant here.
+ props.emplace_back("INTERFACE_LINK_LIBRARIES");
+ props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT");
+ props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE");
for (std::string const& p : props) {
-
- properties[p] = *target->GetProperty(p);
+ cmValue v = target->GetProperty(p);
+ if (!v) {
+ continue;
+ }
+ properties[p] = *v;
if (cmHasLiteralPrefix(p, "IMPORTED_LINK_INTERFACE_LIBRARIES") ||
cmHasLiteralPrefix(p, "IMPORTED_LINK_DEPENDENT_LIBRARIES") ||
@@ -137,3 +150,17 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir(
return install_name_dir;
}
+
+std::string cmExportTryCompileFileGenerator::GetFileSetDirectories(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetDirectoryEntries(), ";"));
+}
+
+std::string cmExportTryCompileFileGenerator::GetFileSetFiles(
+ cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
+{
+ return cmOutputConverter::EscapeForCMake(
+ cmJoin(fileSet->GetFileEntries(), ";"));
+}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 127b8df..8a1fd7e 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -11,9 +11,11 @@
#include "cmExportFileGenerator.h"
+class cmFileSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
+class cmTargetExport;
class cmExportTryCompileFileGenerator : public cmExportFileGenerator
{
@@ -48,6 +50,13 @@ protected:
std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
+ std::string GetFileSetDirectories(cmGeneratorTarget* target,
+ cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
+ std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
+ cmTargetExport* te) override;
+
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index e2c54d7..988c5c3 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -677,6 +677,12 @@ std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
} else {
compiler = "pgi"; // does not exist as default in CodeBlocks 16.01
}
+ } else if (compilerId == "LCC") {
+ if (pureFortran) {
+ compiler = "lfortran";
+ } else {
+ compiler = "lcc";
+ }
} else if (compilerId == "GNU") {
if (pureFortran) {
compiler = "gfortran";
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index fa93b04..19e87d5 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -435,8 +435,7 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes(
lg->GetIncludeDirectories(includes, target, language, config);
std::string includesString =
- lg->GetIncludeFlags(includes, target, language, config, false,
- cmLocalGenerator::IncludePathStyle::Absolute);
+ lg->GetIncludeFlags(includes, target, language, config, false);
return includesString;
}
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index 77d5795..80c069f 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -3,14 +3,17 @@
#include "cmFLTKWrapUICommand.h"
#include <cstddef>
+#include <utility>
+#include <cm/memory>
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -95,15 +98,17 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args,
});
// Add command for generating the .h and .cxx files
- std::string no_main_dependency;
- const char* no_comment = nullptr;
- const char* no_working_dir = nullptr;
- mf.AddCustomCommandToOutput(cxxres, depends, no_main_dependency,
- commandLines, no_comment, no_working_dir,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
- mf.AddCustomCommandToOutput(hname, depends, no_main_dependency,
- commandLines, no_comment, no_working_dir,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
+
+ auto hcc = cm::make_unique<cmCustomCommand>();
+ hcc->SetDepends(depends);
+ hcc->SetCommandLines(commandLines);
+ auto ccc = cm::make_unique<cmCustomCommand>(*hcc);
+
+ hcc->SetOutputs(cxxres);
+ mf.AddCustomCommandToOutput(std::move(hcc));
+
+ ccc->SetOutputs(hname);
+ mf.AddCustomCommandToOutput(std::move(ccc));
cmSourceFile* sf = mf.GetSource(cxxres);
sf->AddDepend(hname);
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index d529f52..c1df992 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -686,7 +686,8 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
-static unsigned int const CodeModelV2Minor = 3;
+// Update Help/manual/cmake-file-api.7.rst when updating this constant.
+static unsigned int const CodeModelV2Minor = 4;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 147181e..40e1d2e 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -23,11 +23,13 @@
#include "cmCryptoHash.h"
#include "cmExportSet.h"
#include "cmFileAPI.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmInstallGetRuntimeDependenciesGenerator.h"
@@ -1043,6 +1045,53 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
installer["runtimeDependencySetType"] = "library";
break;
}
+ } else if (auto* installFileSet =
+ dynamic_cast<cmInstallFileSetGenerator*>(gen)) {
+ installer["type"] = "fileSet";
+ installer["destination"] = installFileSet->GetDestination(this->Config);
+
+ auto* fileSet = installFileSet->GetFileSet();
+ auto* target = installFileSet->GetTarget();
+
+ auto dirCges = fileSet->CompileDirectoryEntries();
+ auto dirs = fileSet->EvaluateDirectoryEntries(
+ dirCges, target->GetLocalGenerator(), this->Config, target);
+
+ auto entryCges = fileSet->CompileFileEntries();
+ std::map<std::string, std::vector<std::string>> entries;
+ for (auto const& entryCge : entryCges) {
+ fileSet->EvaluateFileEntry(dirs, entries, entryCge,
+ target->GetLocalGenerator(), this->Config,
+ target);
+ }
+
+ Json::Value files = Json::arrayValue;
+ for (auto const& it : entries) {
+ auto dir = it.first;
+ if (!dir.empty()) {
+ dir += '/';
+ }
+ for (auto const& file : it.second) {
+ files.append(this->DumpInstallerPath(
+ this->TopSource, file,
+ cmStrCat(dir, cmSystemTools::GetFilenameName(file))));
+ }
+ }
+ installer["paths"] = std::move(files);
+ installer["fileSetName"] = fileSet->GetName();
+ installer["fileSetType"] = fileSet->GetType();
+ installer["fileSetDirectories"] = Json::arrayValue;
+ for (auto const& dir : dirs) {
+ installer["fileSetDirectories"].append(
+ RelativeIfUnder(this->TopSource, dir));
+ }
+ installer["fileSetTarget"] = Json::objectValue;
+ installer["fileSetTarget"]["id"] = TargetId(target, this->TopBuild);
+ installer["fileSetTarget"]["index"] = this->TargetIndexMap[target];
+
+ if (installFileSet->GetOptional()) {
+ installer["isOptional"] = true;
+ }
}
// Add fields common to all install generators.
diff --git a/Source/cmFileAPIToolchains.cxx b/Source/cmFileAPIToolchains.cxx
index b3540c9..fe2972f 100644
--- a/Source/cmFileAPIToolchains.cxx
+++ b/Source/cmFileAPIToolchains.cxx
@@ -30,10 +30,6 @@ class Toolchains
cmFileAPI& FileAPI;
unsigned long Version;
- static const std::vector<ToolchainVariable> CompilerVariables;
- static const std::vector<ToolchainVariable> CompilerImplicitVariables;
- static const ToolchainVariable SourceFileExtensionsVariable;
-
Json::Value DumpToolchains();
Json::Value DumpToolchain(std::string const& lang);
Json::Value DumpToolchainVariables(
@@ -48,24 +44,6 @@ public:
Json::Value Dump();
};
-const std::vector<ToolchainVariable> Toolchains::CompilerVariables{
- { "path", "COMPILER", false },
- { "id", "COMPILER_ID", false },
- { "version", "COMPILER_VERSION", false },
- { "target", "COMPILER_TARGET", false },
-};
-
-const std::vector<ToolchainVariable> Toolchains::CompilerImplicitVariables{
- { "includeDirectories", "IMPLICIT_INCLUDE_DIRECTORIES", true },
- { "linkDirectories", "IMPLICIT_LINK_DIRECTORIES", true },
- { "linkFrameworkDirectories", "IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", true },
- { "linkLibraries", "IMPLICIT_LINK_LIBRARIES", true },
-};
-
-const ToolchainVariable Toolchains::SourceFileExtensionsVariable{
- "sourceFileExtensions", "SOURCE_FILE_EXTENSIONS", true
-};
-
Toolchains::Toolchains(cmFileAPI& fileAPI, unsigned long version)
: FileAPI(fileAPI)
, Version(version)
@@ -94,6 +72,25 @@ Json::Value Toolchains::DumpToolchains()
Json::Value Toolchains::DumpToolchain(std::string const& lang)
{
+ static const std::vector<ToolchainVariable> CompilerVariables{
+ { "path", "COMPILER", false },
+ { "id", "COMPILER_ID", false },
+ { "version", "COMPILER_VERSION", false },
+ { "target", "COMPILER_TARGET", false },
+ };
+
+ static const std::vector<ToolchainVariable> CompilerImplicitVariables{
+ { "includeDirectories", "IMPLICIT_INCLUDE_DIRECTORIES", true },
+ { "linkDirectories", "IMPLICIT_LINK_DIRECTORIES", true },
+ { "linkFrameworkDirectories", "IMPLICIT_LINK_FRAMEWORK_DIRECTORIES",
+ true },
+ { "linkLibraries", "IMPLICIT_LINK_LIBRARIES", true },
+ };
+
+ static const ToolchainVariable SourceFileExtensionsVariable{
+ "sourceFileExtensions", "SOURCE_FILE_EXTENSIONS", true
+ };
+
const auto& mf =
this->FileAPI.GetCMakeInstance()->GetGlobalGenerator()->GetMakefiles()[0];
Json::Value toolchain = Json::objectValue;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index c3ae228..da2f15f 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -197,15 +197,15 @@ bool HandleReadCommand(std::vector<std::string> const& args,
}
// is there a limit?
- long sizeLimit = -1;
+ std::string::size_type sizeLimit = std::string::npos;
if (!arguments.Limit.empty()) {
- sizeLimit = atoi(arguments.Limit.c_str());
+ std::istringstream(arguments.Limit) >> sizeLimit;
}
// is there an offset?
- long offset = 0;
+ cmsys::ifstream::off_type offset = 0;
if (!arguments.Offset.empty()) {
- offset = atoi(arguments.Offset.c_str());
+ std::istringstream(arguments.Offset) >> offset;
}
file.seekg(offset, std::ios::beg); // explicit ios::beg for IBM VisualAge 6
@@ -215,28 +215,21 @@ bool HandleReadCommand(std::vector<std::string> const& args,
if (arguments.Hex) {
// 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);
+ snprintf(hex, sizeof(hex), "%.2x", c & 0xff);
output += hex;
- if (sizeLimit > 0) {
- sizeLimit--;
- }
+ sizeLimit--;
}
} else {
std::string line;
bool has_newline = false;
while (
- sizeLimit != 0 &&
+ sizeLimit > 0 &&
cmSystemTools::GetLineFromStream(file, line, &has_newline, sizeLimit)) {
- if (sizeLimit > 0) {
- sizeLimit = sizeLimit - static_cast<long>(line.size());
- if (has_newline) {
- sizeLimit--;
- }
- if (sizeLimit < 0) {
- sizeLimit = 0;
- }
+ sizeLimit = sizeLimit - line.size();
+ if (has_newline && sizeLimit > 0) {
+ sizeLimit--;
}
output += line;
if (has_newline) {
@@ -1632,8 +1625,9 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
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));
+ int n =
+ snprintf(buf, sizeof(buf), "[%" KWIML_INT_PRIu64 " bytes data]\n",
+ static_cast<KWIML_INT_uint64_t>(size));
if (n > 0) {
cm::append(vec, buf, buf + n);
}
diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx
index 9d5a6c6..70b8cdb 100644
--- a/Source/cmFileLockResult.cxx
+++ b/Source/cmFileLockResult.cxx
@@ -5,7 +5,6 @@
#include <cerrno>
#include <cstring>
-#define WINMSG_BUF_LEN (1024)
cmFileLockResult cmFileLockResult::MakeOk()
{
return { OK, 0 };
@@ -54,6 +53,7 @@ std::string cmFileLockResult::GetOutputMessage() const
case SYSTEM:
#if defined(_WIN32)
{
+# define WINMSG_BUF_LEN (1024)
char winmsg[WINMSG_BUF_LEN];
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
if (FormatMessageA(flags, NULL, this->ErrorValue,
diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx
new file mode 100644
index 0000000..08d56ba
--- /dev/null
+++ b/Source/cmFileSet.cxx
@@ -0,0 +1,151 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileSet.h"
+
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+cmFileSet::cmFileSet(std::string name, std::string type)
+ : Name(std::move(name))
+ , Type(std::move(type))
+{
+}
+
+void cmFileSet::ClearDirectoryEntries()
+{
+ this->DirectoryEntries.clear();
+}
+
+void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
+{
+ this->DirectoryEntries.push_back(std::move(directories));
+}
+
+void cmFileSet::ClearFileEntries()
+{
+ this->FileEntries.clear();
+}
+
+void cmFileSet::AddFileEntry(BT<std::string> files)
+{
+ this->FileEntries.push_back(std::move(files));
+}
+
+std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+cmFileSet::CompileFileEntries() const
+{
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
+
+ for (auto const& entry : this->FileEntries) {
+ for (auto const& ex : cmExpandedList(entry.Value)) {
+ cmGeneratorExpression ge(entry.Backtrace);
+ auto cge = ge.Parse(ex);
+ result.push_back(std::move(cge));
+ }
+ }
+
+ return result;
+}
+
+std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+cmFileSet::CompileDirectoryEntries() const
+{
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
+
+ for (auto const& entry : this->DirectoryEntries) {
+ for (auto const& ex : cmExpandedList(entry.Value)) {
+ cmGeneratorExpression ge(entry.Backtrace);
+ auto cge = ge.Parse(ex);
+ result.push_back(std::move(cge));
+ }
+ }
+
+ return result;
+}
+
+std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
+ const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges,
+ cmLocalGenerator* lg, const std::string& config,
+ const cmGeneratorTarget* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ std::vector<std::string> result;
+ for (auto const& cge : cges) {
+ auto entry = cge->Evaluate(lg, config, target, dagChecker);
+ auto dirs = cmExpandedList(entry);
+ for (std::string dir : dirs) {
+ if (!cmSystemTools::FileIsFullPath(dir)) {
+ dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
+ }
+ auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
+ for (auto const& priorDir : result) {
+ auto collapsedPriorDir = cmSystemTools::CollapseFullPath(priorDir);
+ if (!cmSystemTools::SameFile(collapsedDir, collapsedPriorDir) &&
+ (cmSystemTools::IsSubDirectory(collapsedDir, collapsedPriorDir) ||
+ cmSystemTools::IsSubDirectory(collapsedPriorDir, collapsedDir))) {
+ lg->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Base directories in file set cannot be subdirectories of each "
+ "other:\n ",
+ priorDir, "\n ", dir),
+ cge->GetBacktrace());
+ return {};
+ }
+ }
+ result.push_back(dir);
+ }
+ }
+ return result;
+}
+
+void cmFileSet::EvaluateFileEntry(
+ const std::vector<std::string>& dirs,
+ std::map<std::string, std::vector<std::string>>& filesPerDir,
+ const std::unique_ptr<cmCompiledGeneratorExpression>& cge,
+ cmLocalGenerator* lg, const std::string& config,
+ const cmGeneratorTarget* target,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
+{
+ auto files = cge->Evaluate(lg, config, target, dagChecker);
+ for (std::string file : cmExpandedList(files)) {
+ if (!cmSystemTools::FileIsFullPath(file)) {
+ file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file);
+ }
+ auto collapsedFile = cmSystemTools::CollapseFullPath(file);
+ bool found = false;
+ std::string relDir;
+ for (auto const& dir : dirs) {
+ auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
+ if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
+ found = true;
+ relDir = cmSystemTools::GetParentDirectory(
+ cmSystemTools::RelativePath(collapsedDir, collapsedFile));
+ break;
+ }
+ }
+ if (!found) {
+ std::ostringstream e;
+ e << "File:\n " << file
+ << "\nmust be in one of the file set's base directories:";
+ for (auto const& dir : dirs) {
+ e << "\n " << dir;
+ }
+ lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
+ cge->GetBacktrace());
+ return;
+ }
+
+ filesPerDir[relDir].push_back(file);
+ }
+}
diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h
new file mode 100644
index 0000000..5ee4a98
--- /dev/null
+++ b/Source/cmFileSet.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. */
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmListFileCache.h"
+
+class cmCompiledGeneratorExpression;
+struct cmGeneratorExpressionDAGChecker;
+class cmGeneratorTarget;
+class cmLocalGenerator;
+
+class cmFileSet
+{
+public:
+ cmFileSet(std::string name, std::string type);
+
+ const std::string& GetName() const { return this->Name; }
+ const std::string& GetType() const { return this->Type; }
+
+ void ClearDirectoryEntries();
+ void AddDirectoryEntry(BT<std::string> directories);
+ const std::vector<BT<std::string>>& GetDirectoryEntries() const
+ {
+ return this->DirectoryEntries;
+ }
+
+ void ClearFileEntries();
+ void AddFileEntry(BT<std::string> files);
+ const std::vector<BT<std::string>>& GetFileEntries() const
+ {
+ return this->FileEntries;
+ }
+
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+ CompileFileEntries() const;
+
+ std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
+ CompileDirectoryEntries() const;
+
+ std::vector<std::string> EvaluateDirectoryEntries(
+ const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges,
+ cmLocalGenerator* lg, const std::string& config,
+ const cmGeneratorTarget* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+ void EvaluateFileEntry(
+ const std::vector<std::string>& dirs,
+ std::map<std::string, std::vector<std::string>>& filesPerDir,
+ const std::unique_ptr<cmCompiledGeneratorExpression>& cge,
+ cmLocalGenerator* lg, const std::string& config,
+ const cmGeneratorTarget* target,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
+
+private:
+ std::string Name;
+ std::string Type;
+ std::vector<BT<std::string>> DirectoryEntries;
+ std::vector<BT<std::string>> FileEntries;
+};
diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h
index 4419880..ccc9633 100644
--- a/Source/cmFileTime.h
+++ b/Source/cmFileTime.h
@@ -24,6 +24,8 @@ public:
#endif
cmFileTime() = default;
~cmFileTime() = default;
+ cmFileTime(const cmFileTime&) = default;
+ cmFileTime& operator=(const cmFileTime&) = default;
/**
* @brief Loads the file time of fileName from the file system
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index a123e44..efc4e3a 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -168,7 +168,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
}
this->ExpandPaths();
- this->ComputeFinalPaths();
+ this->ComputeFinalPaths(IgnorePaths::Yes);
return true;
}
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index bdc9207..7106e4b 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -73,10 +73,17 @@ void cmFindCommon::DebugMessage(std::string const& msg) const
bool cmFindCommon::ComputeIfDebugModeWanted()
{
- return this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE") ||
+ return this->Makefile->GetDebugFindPkgMode() ||
+ this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE") ||
this->Makefile->GetCMakeInstance()->GetDebugFindOutput();
}
+bool cmFindCommon::ComputeIfDebugModeWanted(std::string const& var)
+{
+ return this->ComputeIfDebugModeWanted() ||
+ this->Makefile->GetCMakeInstance()->GetDebugFindOutput(var);
+}
+
void cmFindCommon::InitializeSearchPathGroups()
{
std::vector<PathLabel>* labels;
@@ -240,21 +247,29 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
std::vector<std::string> unrootedPaths = paths;
paths.clear();
+ auto isSameDirectoryOrSubDirectory = [](std::string const& l,
+ std::string const& r) {
+ return (cmSystemTools::GetRealPath(l) == cmSystemTools::GetRealPath(r)) ||
+ cmSystemTools::IsSubDirectory(l, r);
+ };
+
for (std::string const& r : roots) {
for (std::string const& up : unrootedPaths) {
// Place the unrooted path under the current root if it is not
// already inside. Skip the unrooted path if it is relative to
// a user home directory or is empty.
std::string rootedDir;
- if (cmSystemTools::IsSubDirectory(up, r) ||
- (stagePrefix && cmSystemTools::IsSubDirectory(up, *stagePrefix))) {
+ if (isSameDirectoryOrSubDirectory(up, r) ||
+ (stagePrefix && isSameDirectoryOrSubDirectory(up, *stagePrefix))) {
rootedDir = up;
} else if (!up.empty() && up[0] != '~') {
- // Start with the new root.
- rootedDir = cmStrCat(r, '/');
-
- // Append the original path with its old root removed.
- rootedDir += cmSystemTools::SplitPathRootComponent(up);
+ auto const* split = cmSystemTools::SplitPathRootComponent(up);
+ if (split && *split) {
+ // Start with the new root.
+ rootedDir = cmStrCat(r, '/', split);
+ } else {
+ rootedDir = r;
+ }
}
// Store the new path.
@@ -271,14 +286,15 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
{
- // null-terminated list of paths.
- static const char* paths[] = { "CMAKE_SYSTEM_IGNORE_PATH",
- "CMAKE_IGNORE_PATH", nullptr };
+ static constexpr const char* paths[] = {
+ "CMAKE_SYSTEM_IGNORE_PATH",
+ "CMAKE_IGNORE_PATH",
+ };
// Construct the list of path roots with no trailing slashes.
- for (const char** pathName = paths; *pathName; ++pathName) {
+ for (const char* pathName : paths) {
// Get the list of paths to ignore from the variable.
- this->Makefile->GetDefExpandList(*pathName, ignore);
+ this->Makefile->GetDefExpandList(pathName, ignore);
}
for (std::string& i : ignore) {
@@ -293,6 +309,31 @@ void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
ignore.insert(ignoreVec.begin(), ignoreVec.end());
}
+void cmFindCommon::GetIgnoredPrefixPaths(std::vector<std::string>& ignore)
+{
+ static constexpr const char* paths[] = {
+ "CMAKE_SYSTEM_IGNORE_PREFIX_PATH",
+ "CMAKE_IGNORE_PREFIX_PATH",
+ };
+
+ // Construct the list of path roots with no trailing slashes.
+ for (const char* pathName : paths) {
+ // Get the list of paths to ignore from the variable.
+ this->Makefile->GetDefExpandList(pathName, ignore);
+ }
+
+ for (std::string& i : ignore) {
+ cmSystemTools::ConvertToUnixSlashes(i);
+ }
+}
+
+void cmFindCommon::GetIgnoredPrefixPaths(std::set<std::string>& ignore)
+{
+ std::vector<std::string> ignoreVec;
+ this->GetIgnoredPrefixPaths(ignoreVec);
+ ignore.insert(ignoreVec.begin(), ignoreVec.end());
+}
+
bool cmFindCommon::CheckCommonArgument(std::string const& arg)
{
if (arg == "NO_DEFAULT_PATH") {
@@ -347,23 +388,28 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
this->SearchPathSuffixes.push_back(std::move(suffix));
}
-void AddTrailingSlash(std::string& s)
+static void AddTrailingSlash(std::string& s)
{
if (!s.empty() && s.back() != '/') {
s += '/';
}
}
-void cmFindCommon::ComputeFinalPaths()
+void cmFindCommon::ComputeFinalPaths(IgnorePaths ignorePaths)
{
// Filter out ignored paths from the prefix list
- std::set<std::string> ignored;
- this->GetIgnoredPaths(ignored);
+ std::set<std::string> ignoredPaths;
+ std::set<std::string> ignoredPrefixes;
+ if (ignorePaths == IgnorePaths::Yes) {
+ this->GetIgnoredPaths(ignoredPaths);
+ this->GetIgnoredPrefixPaths(ignoredPrefixes);
+ }
// Combine the separate path types, filtering out ignores
this->SearchPaths.clear();
std::vector<PathLabel>& allLabels = this->PathGroupLabelMap[PathGroup::All];
for (PathLabel const& l : allLabels) {
- this->LabeledPaths[l].ExtractWithout(ignored, this->SearchPaths);
+ this->LabeledPaths[l].ExtractWithout(ignoredPaths, ignoredPrefixes,
+ this->SearchPaths);
}
// Expand list of paths inside all search roots.
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index f84242e..5d9b3e1 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -82,12 +82,21 @@ protected:
/** Place a set of search paths under the search roots. */
void RerootPaths(std::vector<std::string>& paths);
- /** Get ignored paths from CMAKE_[SYSTEM_]IGNORE_path variables. */
+ /** Get ignored paths from CMAKE_[SYSTEM_]IGNORE_PATH variables. */
void GetIgnoredPaths(std::vector<std::string>& ignore);
void GetIgnoredPaths(std::set<std::string>& ignore);
+ /** Get ignored paths from CMAKE_[SYSTEM_]IGNORE_PREFIX_PATH variables. */
+ void GetIgnoredPrefixPaths(std::vector<std::string>& ignore);
+ void GetIgnoredPrefixPaths(std::set<std::string>& ignore);
+
/** Compute final search path list (reroot + trailing slash). */
- void ComputeFinalPaths();
+ enum class IgnorePaths
+ {
+ No,
+ Yes,
+ };
+ void ComputeFinalPaths(IgnorePaths ignorePaths);
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
@@ -99,8 +108,9 @@ protected:
void SelectDefaultSearchModes();
/** The `InitialPass` functions of the child classes should set
- this->DebugMode to the result of this. */
+ this->DebugMode to the result of these. */
bool ComputeIfDebugModeWanted();
+ bool ComputeIfDebugModeWanted(std::string const& var);
// Path arguments prior to path manipulation routines
std::vector<std::string> UserHintsArgs;
@@ -129,7 +139,7 @@ protected:
std::map<PathLabel, cmSearchPath> LabeledPaths;
std::vector<std::string> SearchPaths;
- std::set<std::string> SearchPathsEmitted;
+ std::set<cmSearchPath::PathWithPrefix> SearchPathsEmitted;
bool SearchFrameworkFirst;
bool SearchFrameworkOnly;
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index ff04bab..1c4039b 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -32,13 +32,14 @@ cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status)
// cmFindLibraryCommand
bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = this->ComputeIfDebugModeWanted();
this->CMakePathName = "LIBRARY";
if (!this->ParseArguments(argsIn)) {
return false;
}
+ this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);
+
if (this->AlreadyDefined) {
this->NormalizeFindResult();
return true;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 335ebbe..f55d838 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -144,9 +144,6 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]);
}
- this->DebugMode = this->ComputeIfDebugModeWanted();
- this->DebugBuffer.clear();
-
// Lookup target architecture, if any.
if (cmValue arch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
@@ -236,6 +233,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// Always search directly in a generated path.
this->SearchPathSuffixes.emplace_back();
+ // Process debug mode
+ cmMakefile::DebugFindPkgRAII debugFindPkgRAII(this->Makefile, this->Name);
+ this->DebugMode = this->ComputeIfDebugModeWanted();
+
// Parse the arguments.
enum Doing
{
@@ -607,15 +608,14 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
loadedPackage = true;
}
}
-
- if (this->DebugMode) {
- this->DebugMessage(this->DebugBuffer);
- this->DebugBuffer.clear();
- }
}
this->AppendSuccessInformation();
+ if (!this->DebugBuffer.empty()) {
+ this->DebugMessage(this->DebugBuffer);
+ }
+
return loadedPackage;
}
@@ -657,6 +657,16 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode()
this->IgnoredPaths.clear();
this->IgnoredPaths.insert(ignored.begin(), ignored.end());
+ // get igonored prefix paths from vars and reroot them.
+ std::vector<std::string> ignoredPrefixes;
+ this->GetIgnoredPrefixPaths(ignoredPrefixes);
+ this->RerootPaths(ignoredPrefixes);
+
+ // Construct a set of ignored prefix paths
+ this->IgnoredPrefixPaths.clear();
+ this->IgnoredPrefixPaths.insert(ignoredPrefixes.begin(),
+ ignoredPrefixes.end());
+
// Find and load the package.
return this->HandlePackageMode(HandlePackageModeType::Config);
}
@@ -671,7 +681,7 @@ void cmFindPackageCommand::SetVersionVariables(
addDefinition(prefix, version);
char buf[64];
- sprintf(buf, "%u", major);
+ snprintf(buf, sizeof(buf), "%u", major);
addDefinition(prefix + "_MAJOR", buf);
sprintf(buf, "%u", minor);
addDefinition(prefix + "_MINOR", buf);
@@ -776,22 +786,21 @@ void cmFindPackageCommand::RestoreFindDefinitions()
bool cmFindPackageCommand::FindModule(bool& found)
{
- std::string module = cmStrCat("Find", this->Name, ".cmake");
+ std::string moduleFileName = cmStrCat("Find", this->Name, ".cmake");
bool system = false;
- std::string debugBuffer =
- cmStrCat("find_package considered the following paths for ", this->Name,
- ".cmake\n");
+ std::string debugBuffer = cmStrCat(
+ "find_package considered the following paths for ", moduleFileName, ":\n");
std::string mfile = this->Makefile->GetModulesFile(
- module, system, this->DebugMode, debugBuffer);
+ moduleFileName, system, this->DebugMode, debugBuffer);
if (this->DebugMode) {
if (mfile.empty()) {
- debugBuffer = cmStrCat(debugBuffer, "The file was not found.");
+ debugBuffer = cmStrCat(debugBuffer, "The file was not found.\n");
} else {
debugBuffer =
cmStrCat(debugBuffer, "The file was found at\n ", mfile, "\n");
}
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
if (!mfile.empty()) {
@@ -935,11 +944,6 @@ bool cmFindPackageCommand::HandlePackageMode(
result = false;
}
- if (this->DebugMode) {
- this->DebugMessage(this->DebugBuffer);
- this->DebugBuffer.clear();
- }
-
// package not found
if (result && !found) {
// warn if package required or neither quiet nor in config mode
@@ -1105,7 +1109,8 @@ bool cmFindPackageCommand::FindConfig()
if (this->DebugMode) {
this->DebugBuffer = cmStrCat(this->DebugBuffer,
"find_package considered the following "
- "locations for the Config module:\n");
+ "locations for ",
+ this->Name, "'s Config module:\n");
}
// Search for frameworks.
@@ -1297,11 +1302,11 @@ inline std::size_t collectPathsForDebug(std::string& buffer,
{
const auto& paths = searchPath.GetPaths();
if (paths.empty()) {
- buffer += " none";
+ buffer += " none\n";
return 0;
}
for (std::size_t i = startIndex; i < paths.size(); i++) {
- buffer += " " + paths[i] + "\n";
+ buffer += " " + paths[i].Path + "\n";
}
return paths.size();
}
@@ -1338,7 +1343,7 @@ void cmFindPackageCommand::ComputePrefixes()
}
this->FillPrefixesUserGuess();
- this->ComputeFinalPaths();
+ this->ComputeFinalPaths(IgnorePaths::No);
}
void cmFindPackageCommand::FillPrefixesPackageRoot()
@@ -1357,7 +1362,7 @@ void cmFindPackageCommand::FillPrefixesPackageRoot()
std::string debugBuffer = "<PackageName>_ROOT CMake variable "
"[CMAKE_FIND_USE_PACKAGE_ROOT_PATH].\n";
collectPathsForDebug(debugBuffer, paths);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1380,7 +1385,7 @@ void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
paths.AddEnvPath("CMAKE_PREFIX_PATH");
if (this->DebugMode) {
debugBuffer = cmStrCat(debugBuffer,
- "\nCMAKE_PREFIX_PATH env variable "
+ "CMAKE_PREFIX_PATH env variable "
"[CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n");
debugOffset = collectPathsForDebug(debugBuffer, paths, debugOffset);
}
@@ -1390,10 +1395,10 @@ void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
if (this->DebugMode) {
debugBuffer =
cmStrCat(debugBuffer,
- "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env "
+ "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env "
"variables [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n");
collectPathsForDebug(debugBuffer, paths, debugOffset);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1414,10 +1419,10 @@ void cmFindPackageCommand::FillPrefixesCMakeVariable()
if (this->DebugMode) {
debugBuffer =
cmStrCat(debugBuffer,
- "\nCMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables "
+ "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables "
"[CMAKE_FIND_USE_CMAKE_PATH].\n");
collectPathsForDebug(debugBuffer, paths, debugOffset);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1442,7 +1447,7 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment()
std::string debugBuffer = "Standard system environment variables "
"[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].\n";
collectPathsForDebug(debugBuffer, paths);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1472,7 +1477,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry()
"CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].\n";
collectPathsForDebug(debugBuffer,
this->LabeledPaths[PathLabel::UserRegistry]);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1492,7 +1497,7 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry()
"[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].\n";
collectPathsForDebug(debugBuffer,
this->LabeledPaths[PathLabel::SystemRegistry]);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1671,7 +1676,7 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
std::string debugBuffer = "CMake variables defined in the Platform file "
"[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].\n";
collectPathsForDebug(debugBuffer, paths);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1686,7 +1691,7 @@ void cmFindPackageCommand::FillPrefixesUserGuess()
std::string debugBuffer =
"Paths specified by the find_package PATHS option.\n";
collectPathsForDebug(debugBuffer, paths);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -1701,7 +1706,7 @@ void cmFindPackageCommand::FillPrefixesUserHints()
std::string debugBuffer =
"Paths specified by the find_package HINTS option.\n";
collectPathsForDebug(debugBuffer, paths);
- this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer, "\n");
+ this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
}
}
@@ -2278,6 +2283,16 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
return false;
}
+ // Skip this if it's in ignored paths.
+ std::string prefixWithoutSlash = prefix_in;
+ if (prefixWithoutSlash != "/" && prefixWithoutSlash.back() == '/') {
+ prefixWithoutSlash.erase(prefixWithoutSlash.length() - 1);
+ }
+ if (this->IgnoredPaths.count(prefixWithoutSlash) ||
+ this->IgnoredPrefixPaths.count(prefixWithoutSlash)) {
+ return false;
+ }
+
// PREFIX/ (useful on windows or in build trees)
if (this->SearchDirectory(prefix_in)) {
return true;
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index edf32d4..f921bb0 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -203,6 +203,7 @@ private:
std::vector<std::string> Names;
std::vector<std::string> Configs;
std::set<std::string> IgnoredPaths;
+ std::set<std::string> IgnoredPrefixPaths;
std::string DebugBuffer;
/*! the selected sortOrder (None by default)*/
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 3d21167..27074ff 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -29,13 +29,14 @@ cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
// cmFindPathCommand
bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = this->ComputeIfDebugModeWanted();
this->CMakePathName = "INCLUDE";
if (!this->ParseArguments(argsIn)) {
return false;
}
+ this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);
+
if (this->AlreadyDefined) {
this->NormalizeFindResult();
return true;
@@ -64,7 +65,8 @@ std::string cmFindPathCommand::FindHeader()
}
std::string cmFindPathCommand::FindHeaderInFramework(
- std::string const& file, std::string const& dir) const
+ std::string const& file, std::string const& dir,
+ cmFindBaseDebugState& debug) const
{
std::string fileName = file;
std::string frameWorkName;
@@ -87,11 +89,13 @@ std::string cmFindPathCommand::FindHeaderInFramework(
std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
if (cmSystemTools::FileExists(intPath)) {
+ debug.FoundAt(intPath);
if (this->IncludeFileInPath) {
return intPath;
}
return fpath;
}
+ debug.FailedAt(intPath);
}
}
// if it is not found yet or not a framework header, then do a glob search
@@ -102,12 +106,15 @@ std::string cmFindPathCommand::FindHeaderInFramework(
std::vector<std::string> files = globIt.GetFiles();
if (!files.empty()) {
std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
+ debug.FoundAt(fheader);
if (this->IncludeFileInPath) {
return fheader;
}
fheader.resize(fheader.size() - file.size());
return fheader;
}
+
+ // No frameworks matched the glob, so nothing more to add to debug.FailedAt()
return "";
}
@@ -134,8 +141,7 @@ std::string cmFindPathCommand::FindFrameworkHeader(cmFindBaseDebugState& debug)
{
for (std::string const& n : this->Names) {
for (std::string const& sp : this->SearchPaths) {
- std::string fwPath = this->FindHeaderInFramework(n, sp);
- fwPath.empty() ? debug.FailedAt(fwPath) : debug.FoundAt(fwPath);
+ std::string fwPath = this->FindHeaderInFramework(n, sp, debug);
if (!fwPath.empty()) {
return fwPath;
}
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index c7281f1..a7746f6 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -30,7 +30,8 @@ public:
private:
std::string FindHeaderInFramework(std::string const& file,
- std::string const& dir) const;
+ std::string const& dir,
+ cmFindBaseDebugState& debug) const;
std::string FindHeader();
std::string FindNormalHeader(cmFindBaseDebugState& debug);
std::string FindFrameworkHeader(cmFindBaseDebugState& debug);
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 1c87625..780b256 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -104,6 +104,26 @@ struct cmFindProgramHelper
}
bool FileIsExecutable(std::string const& file) const
{
+#ifdef _WIN32
+ if (!this->FileIsExecutableCMP0109(file)) {
+ return false;
+ }
+ // Pretend the Windows "python" app installer alias does not exist.
+ if (cmSystemTools::LowerCase(file).find("/windowsapps/python") !=
+ std::string::npos) {
+ std::string dest;
+ if (cmSystemTools::ReadSymlink(file, dest) &&
+ cmHasLiteralSuffix(dest, "\\AppInstallerPythonRedirector.exe")) {
+ return false;
+ }
+ }
+ return true;
+#else
+ return this->FileIsExecutableCMP0109(file);
+#endif
+ }
+ bool FileIsExecutableCMP0109(std::string const& file) const
+ {
switch (this->PolicyCMP0109) {
case cmPolicies::OLD:
return cmSystemTools::FileExists(file, true);
@@ -157,13 +177,14 @@ cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
// cmFindProgramCommand
bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
{
- this->DebugMode = this->ComputeIfDebugModeWanted();
+
this->CMakePathName = "PROGRAM";
// call cmFindBase::ParseArguments
if (!this->ParseArguments(argsIn)) {
return false;
}
+ this->DebugMode = this->ComputeIfDebugModeWanted(this->VariableName);
if (this->AlreadyDefined) {
this->NormalizeFindResult();
diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx
index d4666d7..40e692d 100644
--- a/Source/cmFunctionBlocker.cxx
+++ b/Source/cmFunctionBlocker.cxx
@@ -27,7 +27,7 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
if (!this->ArgumentsMatch(lff, mf)) {
cmListFileContext const& lfc = this->GetStartingContext();
cmListFileContext closingContext =
- cmListFileContext::FromCommandContext(lff, lfc.FilePath);
+ cmListFileContext::FromListFileFunction(lff, lfc.FilePath);
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
index afa8e9b..34c8824 100644
--- a/Source/cmGccDepfileLexerHelper.cxx
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -113,6 +113,24 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
void cmGccDepfileLexerHelper::sanitizeContent()
{
for (auto it = this->Content.begin(); it != this->Content.end();) {
+ // Remove empty paths and normalize windows paths
+ for (auto pit = it->paths.begin(); pit != it->paths.end();) {
+ if (pit->empty()) {
+ pit = it->paths.erase(pit);
+ } else {
+#if defined(_WIN32)
+ // Unescape the colon following the drive letter.
+ // Some versions of GNU compilers can escape this character.
+ // c\:\path must be transformed to c:\path
+ if (pit->size() >= 3 && std::toupper((*pit)[0]) >= 'A' &&
+ std::toupper((*pit)[0]) <= 'Z' && (*pit)[1] == '\\' &&
+ (*pit)[2] == ':') {
+ pit->erase(1, 1);
+ }
+#endif
+ ++pit;
+ }
+ }
// Remove empty rules
for (auto rit = it->rules.begin(); rit != it->rules.end();) {
if (rit->empty()) {
@@ -121,28 +139,10 @@ void cmGccDepfileLexerHelper::sanitizeContent()
++rit;
}
}
- // Remove the entry if rules are empty
- if (it->rules.empty()) {
+ // Remove the entry if rules are empty or do not have any paths
+ if (it->rules.empty() || it->paths.empty()) {
it = this->Content.erase(it);
} else {
- // Remove empty paths and normalize windows paths
- for (auto pit = it->paths.begin(); pit != it->paths.end();) {
- if (pit->empty()) {
- pit = it->paths.erase(pit);
- } else {
-#if defined(_WIN32)
- // Unescape the colon following the drive letter.
- // Some versions of GNU compilers can escape this character.
- // c\:\path must be transformed to c:\path
- if (pit->size() >= 3 && std::toupper((*pit)[0]) >= 'A' &&
- std::toupper((*pit)[0]) <= 'Z' && (*pit)[1] == '\\' &&
- (*pit)[2] == ':') {
- pit->erase(1, 1);
- }
-#endif
- ++pit;
- }
- }
++it;
}
}
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 06778b1..c86001a 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -136,7 +136,8 @@ void cmGeneratedFileStreamBase::Open(std::string const& name)
this->TempName += this->TempExt;
} else {
char buf[64];
- sprintf(buf, "tmp%05x", cmSystemTools::RandomSeed() & 0xFFFFF);
+ snprintf(buf, sizeof(buf), "tmp%05x",
+ cmSystemTools::RandomSeed() & 0xFFFFF);
this->TempName += buf;
}
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index a1fce55..d4b02a5 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -188,11 +188,13 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
return top->Target == tgt && prop == "LINK_LIBRARIES"_s;
}
- return prop == "LINK_LIBRARIES"_s || prop == "LINK_INTERFACE_LIBRARIES"_s ||
+ return prop == "LINK_LIBRARIES"_s || prop == "INTERFACE_LINK_LIBRARIES"_s ||
+ prop == "INTERFACE_LINK_LIBRARIES_DIRECT"_s ||
+ prop == "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s ||
+ prop == "LINK_INTERFACE_LIBRARIES"_s ||
prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
- cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_") ||
- prop == "INTERFACE_LINK_LIBRARIES"_s;
+ cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_");
}
cmGeneratorExpressionDAGChecker const* cmGeneratorExpressionDAGChecker::Top()
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index c357ee1..396e9c9 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -814,7 +814,8 @@ struct PlatformIdNode : public cmGeneratorExpressionNode
}
return "0";
}
-} platformIdNode;
+};
+static struct PlatformIdNode platformIdNode;
template <cmSystemTools::CompareOp Op>
struct VersionNode : public cmGeneratorExpressionNode
@@ -1261,7 +1262,7 @@ static const struct DeviceLinkNode : public cmGeneratorExpressionNode
}
} deviceLinkNode;
-std::string getLinkedTargetsContent(
+static std::string getLinkedTargetsContent(
cmGeneratorTarget const* target, std::string const& prop,
cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker)
@@ -1830,8 +1831,8 @@ static const char* targetPolicyWhitelist[] = {
#undef TARGET_POLICY_STRING
};
-cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
- const char* policy)
+static cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
+ const char* policy)
{
#define RETURN_POLICY(POLICY) \
if (strcmp(policy, #POLICY) == 0) { \
@@ -1846,7 +1847,7 @@ cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
return cmPolicies::WARN;
}
-cmPolicies::PolicyID policyForString(const char* policy_id)
+static cmPolicies::PolicyID policyForString(const char* policy_id)
{
#define RETURN_POLICY_ID(POLICY_ID) \
if (strcmp(policy_id, #POLICY_ID) == 0) { \
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 8033ef5..63cf2ec 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -25,6 +25,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
+#include "cmFileSet.h"
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -41,6 +42,7 @@
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
+#include "cmSourceGroup.h"
#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -50,17 +52,21 @@
#include "cmTargetPropertyComputer.h"
#include "cmake.h"
-class cmMessenger;
-
namespace {
+using LinkInterfaceFor = cmGeneratorTarget::LinkInterfaceFor;
+
const cmsys::RegularExpression FrameworkRegularExpression(
"^(.*/)?([^/]*)\\.framework/(.*)$");
+const std::string kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES";
+const std::string kINTERFACE_LINK_LIBRARIES_DIRECT =
+ "INTERFACE_LINK_LIBRARIES_DIRECT";
+const std::string kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE =
+ "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE";
}
template <>
cmValue cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
- cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
- cmListFileBacktrace const& /* context */)
+ cmGeneratorTarget const* tgt, cmMakefile const& /* mf */)
{
return tgt->GetSourcesProperty();
}
@@ -173,9 +179,73 @@ private:
BT<std::string> PropertyValue;
};
-std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
-CreateTargetPropertyEntry(const BT<std::string>& propertyValue,
- bool evaluateForBuildsystem = false)
+class TargetPropertyEntryFileSet
+ : public cmGeneratorTarget::TargetPropertyEntry
+{
+public:
+ TargetPropertyEntryFileSet(
+ std::vector<std::string> dirs, bool contextSensitiveDirs,
+ std::unique_ptr<cmCompiledGeneratorExpression> entryCge,
+ const cmFileSet* fileSet, cmLinkImplItem const& item = NoLinkImplItem)
+ : cmGeneratorTarget::TargetPropertyEntry(item)
+ , BaseDirs(std::move(dirs))
+ , ContextSensitiveDirs(contextSensitiveDirs)
+ , EntryCge(std::move(entryCge))
+ , FileSet(fileSet)
+ {
+ }
+
+ const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& /*lang*/) const override
+ {
+ std::map<std::string, std::vector<std::string>> filesPerDir;
+ this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir,
+ this->EntryCge, lg, config, headTarget,
+ dagChecker);
+
+ std::vector<std::string> files;
+ for (auto const& it : filesPerDir) {
+ files.insert(files.end(), it.second.begin(), it.second.end());
+ }
+
+ static std::string filesStr;
+ filesStr = cmJoin(files, ";");
+ return filesStr;
+ }
+
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->EntryCge->GetBacktrace();
+ }
+
+ std::string const& GetInput() const override
+ {
+ return this->EntryCge->GetInput();
+ }
+
+ bool GetHadContextSensitiveCondition() const override
+ {
+ return this->ContextSensitiveDirs ||
+ this->EntryCge->GetHadContextSensitiveCondition();
+ }
+
+private:
+ const std::vector<std::string> BaseDirs;
+ const bool ContextSensitiveDirs;
+ const std::unique_ptr<cmCompiledGeneratorExpression> EntryCge;
+ const cmFileSet* FileSet;
+};
+
+std::unique_ptr<
+ cmGeneratorTarget::
+ TargetPropertyEntry> static CreateTargetPropertyEntry(const BT<std::
+ string>&
+ propertyValue,
+ bool
+ evaluateForBuildsystem =
+ false)
{
if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) {
cmGeneratorExpression ge(propertyValue.Backtrace);
@@ -190,7 +260,7 @@ CreateTargetPropertyEntry(const BT<std::string>& propertyValue,
cm::make_unique<TargetPropertyEntryString>(propertyValue));
}
-void CreatePropertyGeneratorExpressions(
+static void CreatePropertyGeneratorExpressions(
cmBTStringRange entries,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
bool evaluateForBuildsystem = false)
@@ -373,8 +443,8 @@ std::string cmGeneratorTarget::GetExportName() const
cmValue cmGeneratorTarget::GetProperty(const std::string& prop) const
{
- if (cmValue result = cmTargetPropertyComputer::GetProperty(
- this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
+ if (cmValue result =
+ cmTargetPropertyComputer::GetProperty(this, prop, *this->Makefile)) {
return result;
}
if (cmSystemTools::GetFatalErrorOccured()) {
@@ -684,6 +754,12 @@ void cmGeneratorTarget::ClearSourcesCache()
this->LinkImplMap.clear();
}
+void cmGeneratorTarget::ClearLinkInterfaceCache()
+{
+ this->LinkInterfaceMap.clear();
+ this->LinkInterfaceUsageRequirementsOnlyMap.clear();
+}
+
void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
{
this->SourceEntries.insert(
@@ -747,6 +823,9 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
if (!depTgt->IsImported() || excludeImported) {
return;
}
+ if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
+ return;
+ }
if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget,
@@ -1255,7 +1334,7 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
- bool usage_requirements_only) const
+ LinkInterfaceFor interfaceFor) const
{
std::string const key = prop + '@' + context->Config;
auto i = this->MaybeInterfacePropertyExists.find(key);
@@ -1273,7 +1352,7 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
context->HeadTarget ? context->HeadTarget : this;
if (cmLinkInterfaceLibraries const* iface =
this->GetLinkInterfaceLibraries(context->Config, headTarget,
- usage_requirements_only)) {
+ interfaceFor)) {
if (iface->HadHeadSensitiveCondition) {
// With a different head target we may get to a library with
// this interface property.
@@ -1283,8 +1362,8 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
// head target, so we can follow them.
for (cmLinkItem const& lib : iface->Libraries) {
if (lib.Target &&
- lib.Target->MaybeHaveInterfaceProperty(
- prop, context, usage_requirements_only)) {
+ lib.Target->MaybeHaveInterfaceProperty(prop, context,
+ interfaceFor)) {
maybeInterfaceProp = true;
break;
}
@@ -1299,13 +1378,12 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
std::string cmGeneratorTarget::EvaluateInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagCheckerParent,
- bool usage_requirements_only) const
+ LinkInterfaceFor interfaceFor) const
{
std::string result;
// If the property does not appear transitively at all, we are done.
- if (!this->MaybeHaveInterfaceProperty(prop, context,
- usage_requirements_only)) {
+ if (!this->MaybeHaveInterfaceProperty(prop, context, interfaceFor)) {
return result;
}
@@ -1337,7 +1415,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
}
if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(
- context->Config, headTarget, usage_requirements_only)) {
+ context->Config, headTarget, interfaceFor)) {
context->HadContextSensitiveCondition =
context->HadContextSensitiveCondition ||
iface->HadContextSensitiveCondition;
@@ -1355,7 +1433,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
context->Language);
std::string libResult = cmGeneratorExpression::StripEmptyListElements(
lib.Target->EvaluateInterfaceProperty(prop, &libContext, &dagChecker,
- usage_requirements_only));
+ interfaceFor));
if (!libResult.empty()) {
if (result.empty()) {
result = std::move(libResult);
@@ -1409,8 +1487,8 @@ std::string AddLangSpecificInterfaceIncludeDirectories(
}
std::string directories;
- if (const auto* interface =
- target->GetLinkInterfaceLibraries(config, root, true)) {
+ if (const auto* interface = target->GetLinkInterfaceLibraries(
+ config, root, LinkInterfaceFor::Usage)) {
for (const cmLinkItem& library : interface->Libraries) {
if (const cmGeneratorTarget* dependency = library.Target) {
if (cm::contains(dependency->GetAllConfigCompileLanguages(), lang)) {
@@ -1481,7 +1559,7 @@ void addInterfaceEntry(cmGeneratorTarget const* headTarget,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
- bool usage_requirements_only,
+ LinkInterfaceFor interfaceFor,
std::vector<cmLinkImplItem> const& libraries)
{
for (cmLinkImplItem const& lib : libraries) {
@@ -1494,7 +1572,7 @@ void addInterfaceEntry(cmGeneratorTarget const* headTarget,
headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
true, lib.Backtrace, lang);
cmExpandList(lib.Target->EvaluateInterfaceProperty(
- prop, &context, dagChecker, usage_requirements_only),
+ prop, &context, dagChecker, interfaceFor),
ee.Values);
ee.ContextDependent = context.HadContextSensitiveCondition;
entries.Entries.emplace_back(std::move(ee));
@@ -1521,13 +1599,13 @@ enum class IncludeRuntimeInterface
Yes,
No
};
-void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
- std::string const& config, std::string const& prop,
- std::string const& lang,
- cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries,
- IncludeRuntimeInterface searchRuntime,
- bool usage_requirements_only = true)
+void AddInterfaceEntries(
+ cmGeneratorTarget const* headTarget, std::string const& config,
+ std::string const& prop, std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries,
+ IncludeRuntimeInterface searchRuntime,
+ LinkInterfaceFor interfaceFor = LinkInterfaceFor::Usage)
{
if (searchRuntime == IncludeRuntimeInterface::Yes) {
if (cmLinkImplementation const* impl =
@@ -1538,10 +1616,10 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- usage_requirements_only, runtimeLibIt->second);
+ interfaceFor, runtimeLibIt->second);
}
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- usage_requirements_only, impl->Libraries);
+ interfaceFor, impl->Libraries);
}
} else {
if (cmLinkImplementationLibraries const* impl =
@@ -1549,7 +1627,7 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
- usage_requirements_only, impl->Libraries);
+ interfaceFor, impl->Libraries);
}
}
}
@@ -1586,6 +1664,80 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget,
}
}
+void addFileSetEntry(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ cmFileSet const* fileSet,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ auto dirCges = fileSet->CompileDirectoryEntries();
+ auto dirs = fileSet->EvaluateDirectoryEntries(
+ dirCges, headTarget->GetLocalGenerator(), config, headTarget, dagChecker);
+ bool contextSensitiveDirs = false;
+ for (auto const& dirCge : dirCges) {
+ if (dirCge->GetHadContextSensitiveCondition()) {
+ contextSensitiveDirs = true;
+ break;
+ }
+ }
+ cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance();
+ for (auto& entryCge : fileSet->CompileFileEntries()) {
+ TargetPropertyEntryFileSet tpe(dirs, contextSensitiveDirs,
+ std::move(entryCge), fileSet);
+ entries.Entries.emplace_back(
+ EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, tpe));
+ for (auto const& file : entries.Entries.back().Values) {
+ auto* sf = headTarget->Makefile->GetOrCreateSource(file);
+ if (fileSet->GetType() == "HEADERS"_s) {
+ sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
+ }
+
+#ifndef CMAKE_BOOTSTRAP
+ std::string e;
+ std::string w;
+ auto path = sf->ResolveFullPath(&e, &w);
+ if (!w.empty()) {
+ cm->IssueMessage(MessageType::AUTHOR_WARNING, w,
+ headTarget->GetBacktrace());
+ }
+ if (path.empty()) {
+ if (!e.empty()) {
+ cm->IssueMessage(MessageType::FATAL_ERROR, e,
+ headTarget->GetBacktrace());
+ }
+ return;
+ }
+ bool found = false;
+ for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
+ if (sg.MatchesFiles(path)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (fileSet->GetType() == "HEADERS"_s) {
+ headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
+ ->AddGroupFile(path);
+ }
+ }
+#endif
+ }
+ }
+}
+
+void AddFileSetEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) {
+ for (auto const& name : cmExpandedList(entry.Value)) {
+ auto const* headerSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
+ }
+ }
+}
+
bool processSources(cmGeneratorTarget const* tgt,
EvaluatedTargetPropertyEntries& entries,
std::vector<BT<std::string>>& srcs,
@@ -1708,7 +1860,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
&dagChecker, linkInterfaceSourcesEntries,
- IncludeRuntimeInterface::No, true);
+ IncludeRuntimeInterface::No, LinkInterfaceFor::Usage);
std::vector<std::string>::size_type numFilesBefore = files.size();
bool contextDependentInterfaceSources = processSources(
this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
@@ -1723,10 +1875,18 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
uniqueSrcs, debugSources);
}
+ // Collect this target's file sets.
+ std::vector<std::string>::size_type numFilesBefore3 = files.size();
+ EvaluatedTargetPropertyEntries fileSetEntries;
+ AddFileSetEntries(this, config, &dagChecker, fileSetEntries);
+ bool contextDependentFileSets =
+ processSources(this, fileSetEntries, files, uniqueSrcs, debugSources);
+
// Determine if sources are context-dependent or not.
if (!contextDependentDirectSources &&
!(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
- !(contextDependentObjects && numFilesBefore2 < files.size())) {
+ !(contextDependentObjects && numFilesBefore2 < files.size()) &&
+ !(contextDependentFileSets && numFilesBefore3 < files.size())) {
this->SourcesAreContextDependent = Tribool::False;
} else {
this->SourcesAreContextDependent = Tribool::True;
@@ -2538,7 +2698,6 @@ public:
: Config(std::move(config))
, Languages(languages)
, HeadTarget(head)
- , Target(target)
, SecondPass(secondPass)
{
this->Visited.insert(target);
@@ -2547,36 +2706,6 @@ public:
void Visit(cmLinkItem const& item)
{
if (!item.Target) {
- if (item.AsStr().find("::") != std::string::npos) {
- bool noMessage = false;
- MessageType messageType = MessageType::FATAL_ERROR;
- std::ostringstream e;
- switch (this->Target->GetLocalGenerator()->GetPolicyStatus(
- cmPolicies::CMP0028)) {
- case cmPolicies::WARN: {
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n";
- messageType = MessageType::AUTHOR_WARNING;
- } break;
- case cmPolicies::OLD:
- noMessage = true;
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Issue the fatal message.
- break;
- }
-
- if (!noMessage) {
- e << "Target \"" << this->Target->GetName()
- << "\" links to target \"" << item.AsStr()
- << "\" but the target was not found. Perhaps a find_package() "
- "call is missing for an IMPORTED target, or an ALIAS target is "
- "missing?";
- this->Target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- messageType, e.str(), this->Target->GetBacktrace());
- }
- }
return;
}
if (!this->Visited.insert(item.Target).second) {
@@ -2609,7 +2738,6 @@ private:
std::string Config;
std::unordered_set<std::string>& Languages;
cmGeneratorTarget const* HeadTarget;
- const cmGeneratorTarget* Target;
std::set<cmGeneratorTarget const*> Visited;
bool SecondPass;
bool HadLinkLanguageSensitiveCondition = false;
@@ -2923,16 +3051,17 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
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)
+static 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)) {
+ item.Target->GetLinkInterfaceLibraries(config, headTarget,
+ LinkInterfaceFor::Usage)) {
for (cmLinkItem const& lib : iface->Libraries) {
processILibs(config, headTarget, lib, gg, tgts, emitted);
}
@@ -3286,7 +3415,7 @@ void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
{
- const std::string& property = this->GetSafeProperty("CUDA_ARCHITECTURES");
+ std::string property = this->GetSafeProperty("CUDA_ARCHITECTURES");
if (property.empty()) {
switch (this->GetPolicyStatusCMP0104()) {
@@ -3314,6 +3443,28 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
return;
}
+ std::string const& compiler =
+ this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
+
+ // Check for special modes: `all`, `all-major`.
+ if (property == "all" || property == "all-major") {
+ if (compiler == "NVIDIA" &&
+ cmSystemTools::VersionCompare(
+ cmSystemTools::OP_GREATER_EQUAL,
+ this->Makefile->GetDefinition("CMAKE_CUDA_COMPILER_VERSION"),
+ "11.5")) {
+ flags = cmStrCat(flags, " -arch=", property);
+ return;
+ }
+ if (property == "all") {
+ property =
+ *this->Makefile->GetDefinition("CMAKE_CUDA_ARCHITECTURES_ALL");
+ } else if (property == "all-major") {
+ property =
+ *this->Makefile->GetDefinition("CMAKE_CUDA_ARCHITECTURES_ALL_MAJOR");
+ }
+ }
+
struct CudaArchitecture
{
std::string name;
@@ -3355,9 +3506,6 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
}
}
- std::string const& compiler =
- this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
-
if (compiler == "NVIDIA") {
for (CudaArchitecture& architecture : architectures) {
flags +=
@@ -3514,7 +3662,7 @@ void processIncludeDirectories(cmGeneratorTarget const* tgt,
cmLinkImplItem const& item = entry.LinkImplItem;
std::string const& targetName = item.AsStr();
bool const fromImported = item.Target && item.Target->IsImported();
- bool const checkCMP0027 = item.FromGenex;
+ bool const checkCMP0027 = item.CheckCMP0027;
std::string usedIncludes;
for (std::string& entryInclude : entry.Values) {
@@ -4416,7 +4564,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
&dagChecker, entries, IncludeRuntimeInterface::Yes,
- this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
+ this->GetPolicyStatusCMP0099() == cmPolicies::NEW
+ ? LinkInterfaceFor::Link
+ : LinkInterfaceFor::Usage);
processOptions(this, entries, result, uniqueOptions, debugOptions,
"link options", OptionsParse::Shell, this->IsDeviceLink());
@@ -4682,7 +4832,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
&dagChecker, entries, IncludeRuntimeInterface::Yes,
- this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
+ this->GetPolicyStatusCMP0099() == cmPolicies::NEW
+ ? LinkInterfaceFor::Link
+ : LinkInterfaceFor::Usage);
processLinkDirectories(this, entries, result, uniqueDirectories,
debugDirectories);
@@ -4721,7 +4873,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
}
AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
&dagChecker, entries, IncludeRuntimeInterface::Yes,
- this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
+ this->GetPolicyStatusCMP0099() == cmPolicies::NEW
+ ? LinkInterfaceFor::Link
+ : LinkInterfaceFor::Usage);
processOptions(this, entries, result, uniqueOptions, false, "link depends",
OptionsParse::None);
@@ -5692,7 +5846,7 @@ std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
return "(unset)";
}
-std::string compatibilityType(CompatibleType t)
+static std::string compatibilityType(CompatibleType t)
{
switch (t) {
case BoolType:
@@ -5708,7 +5862,7 @@ std::string compatibilityType(CompatibleType t)
return "";
}
-std::string compatibilityAgree(CompatibleType t, bool dominant)
+static std::string compatibilityAgree(CompatibleType t, bool dominant)
{
switch (t) {
case BoolType:
@@ -5798,23 +5952,23 @@ std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
return { lhs == rhs, lhs };
}
-std::pair<bool, const char*> consistentStringProperty(const char* lhs,
- const char* rhs)
+static std::pair<bool, const char*> consistentStringProperty(const char* lhs,
+ const char* rhs)
{
const bool b = strcmp(lhs, rhs) == 0;
return { b, b ? lhs : nullptr };
}
-std::pair<bool, std::string> consistentStringProperty(const std::string& lhs,
- const std::string& rhs)
+static std::pair<bool, std::string> consistentStringProperty(
+ const std::string& lhs, const std::string& rhs)
{
const bool b = lhs == rhs;
return { b, b ? lhs : valueAsString(nullptr) };
}
-std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
- const char* rhs,
- CompatibleType t)
+static std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
+ const char* rhs,
+ CompatibleType t)
{
char* pEnd;
@@ -5865,9 +6019,9 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
return { false, nullptr };
}
-std::pair<bool, std::string> consistentProperty(const std::string& lhs,
- const std::string& rhs,
- CompatibleType t)
+static std::pair<bool, std::string> consistentProperty(const std::string& lhs,
+ const std::string& rhs,
+ CompatibleType t)
{
const std::string null_ptr = valueAsString(nullptr);
@@ -6108,6 +6262,139 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
return i->second.get();
}
+void cmGeneratorTarget::CheckLinkLibraries() const
+{
+ bool linkLibrariesOnlyTargets =
+ this->GetPropertyAsBool("LINK_LIBRARIES_ONLY_TARGETS");
+
+ // Evaluate the link interface of this target if needed for extra checks.
+ if (linkLibrariesOnlyTargets) {
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ for (std::string const& config : configs) {
+ this->GetLinkInterfaceLibraries(config, this, LinkInterfaceFor::Link);
+ }
+ }
+
+ // Check link the implementation for each generated configuration.
+ for (auto const& hmp : this->LinkImplMap) {
+ HeadToLinkImplementationMap const& hm = hmp.second;
+ // There could be several entries used when computing the pre-CMP0022
+ // default link interface. Check only the entry for our own link impl.
+ auto const hmi = hm.find(this);
+ if (hmi == hm.end() || !hmi->second.LibrariesDone) {
+ continue;
+ }
+ for (cmLinkImplItem const& item : hmi->second.Libraries) {
+ if (!this->VerifyLinkItemColons(LinkItemRole::Implementation, item)) {
+ return;
+ }
+ if (linkLibrariesOnlyTargets &&
+ !this->VerifyLinkItemIsTarget(LinkItemRole::Implementation, item)) {
+ return;
+ }
+ }
+ }
+
+ // Check link the interface for each generated combination of
+ // configuration and consuming head target. We should not need to
+ // consider LinkInterfaceUsageRequirementsOnlyMap because its entries
+ // should be a subset of LinkInterfaceMap (with LINK_ONLY left out).
+ for (auto const& hmp : this->LinkInterfaceMap) {
+ for (auto const& hmi : hmp.second) {
+ if (!hmi.second.LibrariesDone) {
+ continue;
+ }
+ for (cmLinkItem const& item : hmi.second.Libraries) {
+ if (!this->VerifyLinkItemColons(LinkItemRole::Interface, item)) {
+ return;
+ }
+ if (linkLibrariesOnlyTargets &&
+ !this->VerifyLinkItemIsTarget(LinkItemRole::Interface, item)) {
+ return;
+ }
+ }
+ }
+ }
+}
+
+namespace {
+cm::string_view missingTargetPossibleReasons =
+ "Possible reasons include:\n"
+ " * There is a typo in the target name.\n"
+ " * A find_package call is missing for an IMPORTED target.\n"
+ " * An ALIAS target is missing.\n"_s;
+}
+
+bool cmGeneratorTarget::VerifyLinkItemColons(LinkItemRole role,
+ cmLinkItem const& item) const
+{
+ if (item.Target || item.AsStr().find("::") == std::string::npos) {
+ return true;
+ }
+ MessageType messageType = MessageType::FATAL_ERROR;
+ std::string e;
+ switch (this->GetLocalGenerator()->GetPolicyStatus(cmPolicies::CMP0028)) {
+ case cmPolicies::WARN: {
+ e = cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0028), "\n");
+ messageType = MessageType::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ return true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+
+ if (role == LinkItemRole::Implementation) {
+ e = cmStrCat(e, "Target \"", this->GetName(), "\" links to");
+ } else {
+ e = cmStrCat(e, "The link interface of target \"", this->GetName(),
+ "\" contains");
+ }
+ e =
+ cmStrCat(e, ":\n ", item.AsStr(), "\n", "but the target was not found. ",
+ missingTargetPossibleReasons);
+ cmListFileBacktrace backtrace = item.Backtrace;
+ if (backtrace.Empty()) {
+ backtrace = this->GetBacktrace();
+ }
+ this->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(messageType, e,
+ backtrace);
+ return false;
+}
+
+bool cmGeneratorTarget::VerifyLinkItemIsTarget(LinkItemRole role,
+ cmLinkItem const& item) const
+{
+ if (item.Target) {
+ return true;
+ }
+ std::string const& str = item.AsStr();
+ if (!str.empty() &&
+ (str[0] == '-' || str[0] == '$' || str[0] == '`' ||
+ str.find_first_of("/\\") != std::string::npos)) {
+ return true;
+ }
+
+ std::string e = cmStrCat("Target \"", this->GetName(),
+ "\" has LINK_LIBRARIES_ONLY_TARGETS enabled, but ",
+ role == LinkItemRole::Implementation
+ ? "it links to"
+ : "its link interface contains",
+ ":\n ", item.AsStr(), "\nwhich is not a target. ",
+ missingTargetPossibleReasons);
+ cmListFileBacktrace backtrace = item.Backtrace;
+ if (backtrace.Empty()) {
+ backtrace = this->GetBacktrace();
+ }
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, e, backtrace);
+ return false;
+}
+
void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const
{
int patch;
@@ -6368,7 +6655,7 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n,
cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
std::string const& n, cmListFileBacktrace const& bt,
- LookupLinkItemScope* scope) const
+ LookupLinkItemScope* scope, LookupSelf lookupSelf) const
{
cm::optional<cmLinkItem> maybeItem;
if (this->IsLinkLookupScope(n, scope->LG)) {
@@ -6376,62 +6663,80 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
}
std::string name = this->CheckCMP0004(n);
- if (name == this->GetName() || name.empty()) {
+ if (name.empty() ||
+ (lookupSelf == LookupSelf::No && name == this->GetName())) {
return maybeItem;
}
maybeItem = this->ResolveLinkItem(BT<std::string>(name, bt), scope->LG);
return maybeItem;
}
-void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
- std::string const& value,
- std::string const& config,
- cmGeneratorTarget const* headTarget,
- bool usage_requirements_only,
- cmLinkInterface& iface) const
+void cmGeneratorTarget::ExpandLinkItems(
+ std::string const& prop, cmBTStringRange entries, std::string const& config,
+ cmGeneratorTarget const* headTarget, LinkInterfaceFor interfaceFor,
+ LinkInterfaceField field, cmLinkInterface& iface) const
{
+ if (entries.empty()) {
+ return;
+ }
// Keep this logic in sync with ComputeLinkImplementationLibraries.
- cmGeneratorExpression ge;
cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
// The $<LINK_ONLY> expression may be in a link interface to specify
// private link dependencies that are otherwise excluded from usage
// requirements.
- if (usage_requirements_only) {
+ if (interfaceFor == LinkInterfaceFor::Usage) {
dagChecker.SetTransitivePropertiesOnly();
}
- std::vector<std::string> libs;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
- cge->SetEvaluateForBuildsystem(true);
- cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget,
- &dagChecker, this, headTarget->LinkerLanguage),
- libs);
cmMakefile const* mf = this->LocalGenerator->GetMakefile();
LookupLinkItemScope scope{ this->LocalGenerator };
- for (std::string const& lib : libs) {
- if (cm::optional<cmLinkItem> maybeItem =
- this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) {
- cmLinkItem item = std::move(*maybeItem);
-
- if (!item.Target) {
- // Report explicitly linked object files separately.
- std::string const& maybeObj = item.AsStr();
- if (cmSystemTools::FileIsFullPath(maybeObj)) {
- cmSourceFile const* sf =
- mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
- if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
- iface.Objects.emplace_back(std::move(item));
- continue;
+ for (BT<std::string> const& entry : entries) {
+ cmGeneratorExpression ge(entry.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(entry.Value);
+ cge->SetEvaluateForBuildsystem(true);
+ std::vector<std::string> libs = cmExpandedList(
+ cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker,
+ this, headTarget->LinkerLanguage));
+ for (std::string const& lib : libs) {
+ if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(
+ lib, cge->GetBacktrace(), &scope,
+ field == LinkInterfaceField::Libraries ? LookupSelf::No
+ : LookupSelf::Yes)) {
+ cmLinkItem item = std::move(*maybeItem);
+
+ if (field == LinkInterfaceField::HeadInclude) {
+ iface.HeadInclude.emplace_back(std::move(item));
+ continue;
+ }
+ if (field == LinkInterfaceField::HeadExclude) {
+ iface.HeadExclude.emplace_back(std::move(item));
+ continue;
+ }
+ if (!item.Target) {
+ // Report explicitly linked object files separately.
+ std::string const& maybeObj = item.AsStr();
+ if (cmSystemTools::FileIsFullPath(maybeObj)) {
+ cmSourceFile const* sf =
+ mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
+ if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+ iface.Objects.emplace_back(std::move(item));
+ continue;
+ }
}
}
- }
- iface.Libraries.emplace_back(std::move(item));
+ iface.Libraries.emplace_back(std::move(item));
+ }
+ }
+ if (cge->GetHadHeadSensitiveCondition()) {
+ iface.HadHeadSensitiveCondition = true;
+ }
+ if (cge->GetHadContextSensitiveCondition()) {
+ iface.HadContextSensitiveCondition = true;
+ }
+ if (cge->GetHadLinkLanguageSensitiveCondition()) {
+ iface.HadLinkLanguageSensitiveCondition = true;
}
}
- iface.HadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
- iface.HadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
- iface.HadLinkLanguageSensitiveCondition =
- cge->GetHadLinkLanguageSensitiveCondition();
}
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
@@ -6446,7 +6751,8 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
{
// Imported targets have their own link interface.
if (this->IsImported()) {
- return this->GetImportLinkInterface(config, head, false, secondPass);
+ return this->GetImportLinkInterface(config, head, LinkInterfaceFor::Link,
+ secondPass);
}
// Link interfaces are not supported for executables that do not
@@ -6459,20 +6765,20 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
// Lookup any existing link interface for this configuration.
cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
- if (secondPass) {
- hm.erase(head);
- }
-
// If the link interface does not depend on the head target
- // then return the one we computed first.
+ // then re-use the one from the head we computed first.
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
- return &hm.begin()->second;
+ head = hm.begin()->first;
}
cmOptionalLinkInterface& iface = hm[head];
+ if (secondPass) {
+ iface = cmOptionalLinkInterface();
+ }
if (!iface.LibrariesDone) {
iface.LibrariesDone = true;
- this->ComputeLinkInterfaceLibraries(config, iface, head, false);
+ this->ComputeLinkInterfaceLibraries(config, iface, head,
+ LinkInterfaceFor::Link);
}
if (!iface.AllDone) {
iface.AllDone = true;
@@ -6566,11 +6872,11 @@ void cmGeneratorTarget::ComputeLinkInterface(
const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
const std::string& config, cmGeneratorTarget const* head,
- bool usage_requirements_only) const
+ LinkInterfaceFor interfaceFor) const
{
// Imported targets have their own link interface.
if (this->IsImported()) {
- return this->GetImportLinkInterface(config, head, usage_requirements_only);
+ return this->GetImportLinkInterface(config, head, interfaceFor);
}
// Link interfaces are not supported for executables that do not
@@ -6582,21 +6888,20 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
// Lookup any existing link interface for this configuration.
cmHeadToLinkInterfaceMap& hm =
- (usage_requirements_only
+ (interfaceFor == LinkInterfaceFor::Usage
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
: this->GetHeadToLinkInterfaceMap(config));
// If the link interface does not depend on the head target
- // then return the one we computed first.
+ // then re-use the one from the head we computed first.
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
- return &hm.begin()->second;
+ head = hm.begin()->first;
}
cmOptionalLinkInterface& iface = hm[head];
if (!iface.LibrariesDone) {
iface.LibrariesDone = true;
- this->ComputeLinkInterfaceLibraries(config, iface, head,
- usage_requirements_only);
+ this->ComputeLinkInterfaceLibraries(config, iface, head, interfaceFor);
}
return iface.Exists ? &iface : nullptr;
@@ -6857,7 +7162,7 @@ bool cmGeneratorTarget::GetRPATH(const std::string& config,
void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
const std::string& config, cmOptionalLinkInterface& iface,
- cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
+ cmGeneratorTarget const* headTarget, LinkInterfaceFor interfaceFor) const
{
// Construct the property name suffix for this configuration.
std::string suffix = "_";
@@ -6869,59 +7174,66 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
- cmValue explicitLibraries = nullptr;
- std::string linkIfaceProp;
+ bool haveExplicitLibraries = false;
+ cmValue explicitLibrariesCMP0022OLD;
+ std::string linkIfacePropCMP0022OLD;
bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
this->GetPolicyStatusCMP0022() != cmPolicies::WARN);
if (cmp0022NEW) {
// CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
- linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
- explicitLibraries = this->GetProperty(linkIfaceProp);
- } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
- this->IsExecutableWithExports()) {
+ haveExplicitLibraries = !this->Target->GetLinkInterfaceEntries().empty() ||
+ !this->Target->GetLinkInterfaceDirectEntries().empty() ||
+ !this->Target->GetLinkInterfaceDirectExcludeEntries().empty();
+ } else {
// CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
// shared lib or executable.
-
- // Lookup the per-configuration property.
- linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
- explicitLibraries = this->GetProperty(linkIfaceProp);
-
- // If not set, try the generic property.
- if (!explicitLibraries) {
- linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
- explicitLibraries = this->GetProperty(linkIfaceProp);
+ if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports()) {
+ // Lookup the per-configuration property.
+ linkIfacePropCMP0022OLD = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
+ explicitLibrariesCMP0022OLD = this->GetProperty(linkIfacePropCMP0022OLD);
+
+ // If not set, try the generic property.
+ if (!explicitLibrariesCMP0022OLD) {
+ linkIfacePropCMP0022OLD = "LINK_INTERFACE_LIBRARIES";
+ explicitLibrariesCMP0022OLD =
+ this->GetProperty(linkIfacePropCMP0022OLD);
+ }
}
- }
- 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.
- cmValue newExplicitLibraries =
- this->GetProperty("INTERFACE_LINK_LIBRARIES");
- if (newExplicitLibraries &&
- (*newExplicitLibraries != *explicitLibraries)) {
- 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 << "\n";
- /* clang-format on */
- this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
- this->PolicyWarnedCMP0022 = true;
+ if (explicitLibrariesCMP0022OLD &&
+ 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.
+ cmValue newExplicitLibraries =
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if (newExplicitLibraries &&
+ (*newExplicitLibraries != *explicitLibrariesCMP0022OLD)) {
+ 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 " <<
+ linkIfacePropCMP0022OLD << " properties."
+ "\n"
+ "INTERFACE_LINK_LIBRARIES:\n"
+ " " << *newExplicitLibraries << "\n" <<
+ linkIfacePropCMP0022OLD << ":\n"
+ " " << *explicitLibrariesCMP0022OLD << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING,
+ w.str());
+ this->PolicyWarnedCMP0022 = true;
+ }
}
+
+ haveExplicitLibraries = static_cast<bool>(explicitLibrariesCMP0022OLD);
}
// There is no implicit link interface for executables or modules
// so if none was explicitly set then there is no link interface.
- if (!explicitLibraries &&
+ if (!haveExplicitLibraries &&
(this->GetType() == cmStateEnums::EXECUTABLE ||
(this->GetType() == cmStateEnums::MODULE_LIBRARY))) {
return;
@@ -6931,12 +7243,29 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// If CMP0022 is NEW then the plain tll signature sets the
// INTERFACE_LINK_LIBRARIES property. Even if the project
// clears it, the link interface is still explicit.
- iface.Explicit = cmp0022NEW || explicitLibraries;
+ iface.Explicit = cmp0022NEW || explicitLibrariesCMP0022OLD;
- if (explicitLibraries) {
- // The interface libraries have been explicitly set.
- this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config,
- headTarget, usage_requirements_only, iface);
+ if (cmp0022NEW) {
+ // The interface libraries are specified by INTERFACE_LINK_LIBRARIES.
+ // Use its special representation directly to get backtraces.
+ this->ExpandLinkItems(
+ kINTERFACE_LINK_LIBRARIES, this->Target->GetLinkInterfaceEntries(),
+ config, headTarget, interfaceFor, LinkInterfaceField::Libraries, iface);
+ this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
+ this->Target->GetLinkInterfaceDirectEntries(),
+ config, headTarget, interfaceFor,
+ LinkInterfaceField::HeadInclude, iface);
+ this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
+ this->Target->GetLinkInterfaceDirectExcludeEntries(),
+ config, headTarget, interfaceFor,
+ LinkInterfaceField::HeadExclude, iface);
+ } else if (explicitLibrariesCMP0022OLD) {
+ // The interface libraries have been explicitly set in pre-CMP0022 style.
+ std::vector<BT<std::string>> entries;
+ entries.emplace_back(*explicitLibrariesCMP0022OLD);
+ this->ExpandLinkItems(linkIfacePropCMP0022OLD, cmMakeRange(entries),
+ config, headTarget, interfaceFor,
+ LinkInterfaceField::Libraries, iface);
}
// If the link interface is explicit, do not fall back to the link impl.
@@ -6950,15 +7279,14 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
iface.Libraries.insert(iface.Libraries.end(), impl->Libraries.begin(),
impl->Libraries.end());
if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
- !this->PolicyWarnedCMP0022 && !usage_requirements_only) {
+ !this->PolicyWarnedCMP0022 && interfaceFor == LinkInterfaceFor::Link) {
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
cmLinkInterface ifaceNew;
- static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
- if (cmValue newExplicitLibraries = this->GetProperty(newProp)) {
- this->ExpandLinkItems(newProp, *newExplicitLibraries, config,
- headTarget, usage_requirements_only, ifaceNew);
- }
+ this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES,
+ this->Target->GetLinkInterfaceEntries(), config,
+ headTarget, interfaceFor,
+ LinkInterfaceField::Libraries, ifaceNew);
if (ifaceNew.Libraries != iface.Libraries) {
std::string oldLibraries = cmJoin(impl->Libraries, ";");
std::string newLibraries = cmJoin(ifaceNew.Libraries, ";");
@@ -7071,7 +7399,7 @@ void cmGeneratorTarget::ComputeLinkImplementationRuntimeLibraries(
const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
const std::string& config, cmGeneratorTarget const* headTarget,
- bool usage_requirements_only, bool secondPass) const
+ LinkInterfaceFor interfaceFor, bool secondPass) const
{
cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
if (!info) {
@@ -7079,32 +7407,41 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
}
cmHeadToLinkInterfaceMap& hm =
- (usage_requirements_only
+ (interfaceFor == LinkInterfaceFor::Usage
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
: this->GetHeadToLinkInterfaceMap(config));
- if (secondPass) {
- hm.erase(headTarget);
- }
-
// If the link interface does not depend on the head target
- // then return the one we computed first.
+ // then re-use the one from the head we computed first.
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
- return &hm.begin()->second;
+ headTarget = hm.begin()->first;
}
cmOptionalLinkInterface& iface = hm[headTarget];
+ if (secondPass) {
+ iface = cmOptionalLinkInterface();
+ }
if (!iface.AllDone) {
iface.AllDone = true;
+ iface.LibrariesDone = true;
iface.Multiplicity = info->Multiplicity;
cmExpandList(info->Languages, iface.Languages);
- this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
- headTarget, usage_requirements_only, iface);
+ this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
+ cmMakeRange(info->LibrariesHeadInclude), config,
+ headTarget, interfaceFor,
+ LinkInterfaceField::HeadInclude, iface);
+ this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
+ cmMakeRange(info->LibrariesHeadExclude), config,
+ headTarget, interfaceFor,
+ LinkInterfaceField::HeadExclude, iface);
+ this->ExpandLinkItems(info->LibrariesProp, cmMakeRange(info->Libraries),
+ config, headTarget, interfaceFor,
+ LinkInterfaceField::Libraries, iface);
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
LookupLinkItemScope scope{ this->LocalGenerator };
for (std::string const& dep : deps) {
- if (cm::optional<cmLinkItem> maybeItem =
- this->LookupLinkItem(dep, cmListFileBacktrace(), &scope)) {
+ if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(
+ dep, cmListFileBacktrace(), &scope, LookupSelf::No)) {
iface.SharedDeps.emplace_back(std::move(*maybeItem));
}
}
@@ -7170,24 +7507,35 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link interface.
{
- std::string linkProp = "INTERFACE_LINK_LIBRARIES";
- cmValue propertyLibs = this->GetProperty(linkProp);
-
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- if (!propertyLibs) {
- linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
- propertyLibs = this->GetProperty(linkProp);
+ // Use the INTERFACE_LINK_LIBRARIES special representation directly
+ // to get backtraces.
+ cmBTStringRange entries = this->Target->GetLinkInterfaceEntries();
+ if (!entries.empty()) {
+ info.LibrariesProp = "INTERFACE_LINK_LIBRARIES";
+ for (BT<std::string> const& entry : entries) {
+ info.Libraries.emplace_back(entry);
}
-
+ } else if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ std::string linkProp =
+ cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
+ cmValue propertyLibs = this->GetProperty(linkProp);
if (!propertyLibs) {
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
propertyLibs = this->GetProperty(linkProp);
}
+ if (propertyLibs) {
+ info.LibrariesProp = linkProp;
+ info.Libraries.emplace_back(*propertyLibs);
+ }
}
- if (propertyLibs) {
- info.LibrariesProp = linkProp;
- info.Libraries = *propertyLibs;
- }
+ }
+ for (BT<std::string> const& entry :
+ this->Target->GetLinkInterfaceDirectEntries()) {
+ info.LibrariesHeadInclude.emplace_back(entry);
+ }
+ for (BT<std::string> const& entry :
+ this->Target->GetLinkInterfaceDirectExcludeEntries()) {
+ info.LibrariesHeadExclude.emplace_back(entry);
}
if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
if (loc) {
@@ -7549,6 +7897,11 @@ bool cmGeneratorTarget::IsCSharpOnly() const
return languages.size() == 1 && languages.count("CSharp") > 0;
}
+bool cmGeneratorTarget::IsDotNetSdkTarget() const
+{
+ return !this->GetProperty("DOTNET_SDK").IsEmpty();
+}
+
void cmGeneratorTarget::ComputeLinkImplementationLanguages(
const std::string& config, cmOptionalLinkImplementation& impl) const
{
@@ -7598,9 +7951,9 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
this->LinkImplMap[cmSystemTools::UpperCase(config)];
// If the link implementation does not depend on the head target
- // then return the one we computed first.
+ // then re-use the one from the head we computed first.
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
- return &hm.begin()->second;
+ head = hm.begin()->first;
}
cmOptionalLinkImplementation& impl = hm[head];
@@ -7617,6 +7970,112 @@ bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
return cm::contains(this->LinkImplicitNullProperties, p);
}
+namespace {
+class TransitiveLinkImpl
+{
+ cmGeneratorTarget const* Self;
+ std::string const& Config;
+ cmLinkImplementation& Impl;
+
+ std::set<cmLinkItem> Emitted;
+ std::set<cmLinkItem> Excluded;
+ std::unordered_set<cmGeneratorTarget const*> Followed;
+
+ void Follow(cmGeneratorTarget const* target);
+
+public:
+ TransitiveLinkImpl(cmGeneratorTarget const* self, std::string const& config,
+ cmLinkImplementation& impl)
+ : Self(self)
+ , Config(config)
+ , Impl(impl)
+ {
+ }
+
+ void Compute();
+};
+
+void TransitiveLinkImpl::Follow(cmGeneratorTarget const* target)
+{
+ if (!target || !this->Followed.insert(target).second ||
+ target->GetPolicyStatusCMP0022() == cmPolicies::OLD ||
+ target->GetPolicyStatusCMP0022() == cmPolicies::WARN) {
+ return;
+ }
+
+ // Get this target's usage requirements.
+ cmLinkInterfaceLibraries const* iface = target->GetLinkInterfaceLibraries(
+ this->Config, this->Self, LinkInterfaceFor::Usage);
+ if (!iface) {
+ return;
+ }
+ if (iface->HadContextSensitiveCondition) {
+ this->Impl.HadContextSensitiveCondition = true;
+ }
+
+ // Process 'INTERFACE_LINK_LIBRARIES_DIRECT' usage requirements.
+ for (cmLinkItem const& item : iface->HeadInclude) {
+ // Inject direct dependencies from the item's usage requirements
+ // before the item itself.
+ this->Follow(item.Target);
+
+ // Add the item itself, but at most once.
+ if (this->Emitted.insert(item).second) {
+ this->Impl.Libraries.emplace_back(item, /* checkCMP0027= */ false);
+ }
+ }
+
+ // Follow transitive dependencies.
+ for (cmLinkItem const& item : iface->Libraries) {
+ this->Follow(item.Target);
+ }
+
+ // Record exclusions from 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
+ // usage requirements.
+ for (cmLinkItem const& item : iface->HeadExclude) {
+ this->Excluded.insert(item);
+ }
+}
+
+void TransitiveLinkImpl::Compute()
+{
+ // Save the original items and start with an empty list.
+ std::vector<cmLinkImplItem> original = std::move(this->Impl.Libraries);
+
+ // Avoid injecting any original items as usage requirements.
+ // This gives LINK_LIBRARIES final control over the order
+ // if it explicitly lists everything.
+ this->Emitted.insert(original.cbegin(), original.cend());
+
+ // Process each original item.
+ for (cmLinkImplItem& item : original) {
+ // Inject direct dependencies listed in 'INTERFACE_LINK_LIBRARIES_DIRECT'
+ // usage requirements before the item itself.
+ this->Follow(item.Target);
+
+ // Add the item itself.
+ this->Impl.Libraries.emplace_back(std::move(item));
+ }
+
+ // Remove items listed in 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
+ // usage requirements found through any dependency above.
+ this->Impl.Libraries.erase(
+ std::remove_if(this->Impl.Libraries.begin(), this->Impl.Libraries.end(),
+ [this](cmLinkImplItem const& item) {
+ return this->Excluded.find(item) != this->Excluded.end();
+ }),
+ this->Impl.Libraries.end());
+}
+
+void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
+ std::string const& config,
+ cmLinkImplementation& impl)
+{
+ TransitiveLinkImpl transitiveLinkImpl(self, config, impl);
+ transitiveLinkImpl.Compute();
+}
+}
+
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
const std::string& config, cmOptionalLinkImplementation& impl,
cmGeneratorTarget const* head) const
@@ -7637,7 +8096,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
std::string const& evaluated =
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
this->LinkerLanguage);
- bool const fromGenex = evaluated != entry.Value;
+ bool const checkCMP0027 = evaluated != entry.Value;
cmExpandList(evaluated, llibs);
if (cge->GetHadHeadSensitiveCondition()) {
impl.HadHeadSensitiveCondition = true;
@@ -7711,7 +8170,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
}
- impl.Libraries.emplace_back(std::move(item), fromGenex);
+ impl.Libraries.emplace_back(std::move(item), checkCMP0027);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
@@ -7723,6 +8182,11 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
}
+ // Update the list of direct link dependencies from usage requirements.
+ if (head == this) {
+ ComputeLinkImplTransitive(this, config, impl);
+ }
+
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
@@ -7804,6 +8268,26 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(BT<std::string> const& name,
return cmLinkItem(resolved.Target, false, bt);
}
+bool cmGeneratorTarget::HasPackageReferences() const
+{
+ return this->IsInBuildSystem() &&
+ !this->GetProperty("VS_PACKAGE_REFERENCES")->empty();
+}
+
+std::vector<std::string> cmGeneratorTarget::GetPackageReferences() const
+{
+ std::vector<std::string> packageReferences;
+
+ if (this->IsInBuildSystem()) {
+ if (cmValue vsPackageReferences =
+ this->GetProperty("VS_PACKAGE_REFERENCES")) {
+ cmExpandList(*vsPackageReferences, packageReferences);
+ }
+ }
+
+ return packageReferences;
+}
+
std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
{
if (OutputInfo const* info = this->GetOutputInfo(config)) {
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 9906963..45639c0 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -16,6 +16,7 @@
#include <cm/optional>
+#include "cmAlgorithms.h"
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
@@ -83,6 +84,10 @@ public:
cmComputeLinkInformation* GetLinkInformation(
const std::string& config) const;
+ // Perform validation checks on memoized link structures.
+ // Call this after generation is complete.
+ void CheckLinkLibraries() const;
+
cmStateEnums::TargetType GetType() const;
const std::string& GetName() const;
std::string GetExportName() const;
@@ -237,14 +242,20 @@ public:
cmOptionalLinkInterface& iface,
const cmGeneratorTarget* head) const;
+ enum class LinkInterfaceFor
+ {
+ Usage, // Interface for usage requirements excludes $<LINK_ONLY>.
+ Link, // Interface for linking includes $<LINK_ONLY>.
+ };
+
cmLinkInterfaceLibraries const* GetLinkInterfaceLibraries(
const std::string& config, const cmGeneratorTarget* headTarget,
- bool usage_requirements_only) const;
+ LinkInterfaceFor interfaceFor) const;
void ComputeLinkInterfaceLibraries(const std::string& config,
cmOptionalLinkInterface& iface,
const cmGeneratorTarget* head,
- bool usage_requirements_only) const;
+ LinkInterfaceFor interfaceFor) const;
/** Get the library name for an imported interface library. */
std::string GetImportedLibName(std::string const& config) const;
@@ -413,6 +424,9 @@ public:
cmLinkItem ResolveLinkItem(BT<std::string> const& name,
cmLocalGenerator const* lg) const;
+ bool HasPackageReferences() const;
+ std::vector<std::string> GetPackageReferences() 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
@@ -425,6 +439,8 @@ public:
bool IsCSharpOnly() const;
+ bool IsDotNetSdkTarget() const;
+
void GetObjectLibrariesCMP0026(
std::vector<cmGeneratorTarget*>& objlibs) const;
@@ -651,6 +667,9 @@ public:
*/
void ClearSourcesCache();
+ // Do not use. This is only for a specific call site with a FIXME comment.
+ void ClearLinkInterfaceCache();
+
void AddSource(const std::string& src, bool before = false);
void AddTracedSources(std::vector<std::string> const& srcs);
@@ -781,7 +800,7 @@ public:
std::string EvaluateInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagCheckerParent,
- bool usage_requirements_only = true) const;
+ LinkInterfaceFor interfaceFor = LinkInterfaceFor::Usage) const;
bool HaveInstallTreeRPATH(const std::string& config) const;
@@ -966,6 +985,14 @@ private:
cmLinkImplementation const* GetLinkImplementation(const std::string& config,
bool secondPass) const;
+ enum class LinkItemRole
+ {
+ Implementation,
+ Interface,
+ };
+ bool VerifyLinkItemIsTarget(LinkItemRole role, cmLinkItem const& item) const;
+ bool VerifyLinkItemColons(LinkItemRole role, cmLinkItem const& item) const;
+
// Cache import information from properties for each configuration.
struct ImportInfo
{
@@ -977,8 +1004,10 @@ private:
std::string ImportLibrary;
std::string LibName;
std::string Languages;
- std::string Libraries;
std::string LibrariesProp;
+ std::vector<BT<std::string>> Libraries;
+ std::vector<BT<std::string>> LibrariesHeadInclude;
+ std::vector<BT<std::string>> LibrariesHeadExclude;
std::string SharedDeps;
};
@@ -994,7 +1023,7 @@ private:
cmLinkInterface const* GetImportLinkInterface(const std::string& config,
const cmGeneratorTarget* head,
- bool usage_requirements_only,
+ LinkInterfaceFor interfaceFor,
bool secondPass = false) const;
using KindedSourcesMapType = std::map<std::string, KindedSources>;
@@ -1008,7 +1037,7 @@ private:
mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
bool MaybeHaveInterfaceProperty(std::string const& prop,
cmGeneratorExpressionContext* context,
- bool usage_requirements_only) const;
+ LinkInterfaceFor interfaceFor) const;
using TargetPropertyEntryVector =
std::vector<std::unique_ptr<TargetPropertyEntry>>;
@@ -1039,19 +1068,31 @@ private:
bool IsLinkLookupScope(std::string const& n,
cmLocalGenerator const*& lg) const;
- void ExpandLinkItems(std::string const& prop, std::string const& value,
+ enum class LinkInterfaceField
+ {
+ Libraries,
+ HeadExclude,
+ HeadInclude,
+ };
+ void ExpandLinkItems(std::string const& prop, cmBTStringRange entries,
std::string const& config,
const cmGeneratorTarget* headTarget,
- bool usage_requirements_only,
+ LinkInterfaceFor interfaceFor, LinkInterfaceField field,
cmLinkInterface& iface) const;
struct LookupLinkItemScope
{
cmLocalGenerator const* LG;
};
+ enum class LookupSelf
+ {
+ No,
+ Yes,
+ };
cm::optional<cmLinkItem> LookupLinkItem(std::string const& n,
cmListFileBacktrace const& bt,
- LookupLinkItemScope* scope) const;
+ LookupLinkItemScope* scope,
+ LookupSelf lookupSelf) const;
std::vector<BT<std::string>> GetSourceFilePaths(
std::string const& config) const;
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 162860a..4a25311 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -7,7 +7,6 @@
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
-#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -23,8 +22,6 @@
#include "cmValue.h"
#include "cmake.h"
-class cmMessenger;
-
namespace {
enum OutType
{
@@ -187,7 +184,8 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
scope)) {
output = def->GetShortDescription();
- } else {
+ }
+ if (output.empty()) {
output = "NOTFOUND";
}
status.GetMakefile().AddDefinition(variable, output);
@@ -198,7 +196,8 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
scope)) {
output = def->GetFullDescription();
- } else {
+ }
+ if (output.empty()) {
output = "NOTFOUND";
}
status.GetMakefile().AddDefinition(variable, output);
@@ -365,9 +364,8 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
}
return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
}
- cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
- cmMessenger* messenger = status.GetMakefile().GetMessenger();
- cmValue prop = target->GetComputedProperty(propertyName, messenger, bt);
+ cmValue prop =
+ target->GetComputedProperty(propertyName, status.GetMakefile());
if (!prop) {
prop = target->GetProperty(propertyName);
}
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 12c8221..e1ae9b2 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -6,15 +6,12 @@
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
-#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmTarget.h"
#include "cmValue.h"
-class cmMessenger;
-
bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -43,9 +40,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
}
} else if (!args[2].empty()) {
cmValue prop_cstr = nullptr;
- cmListFileBacktrace bt = mf.GetBacktrace();
- cmMessenger* messenger = mf.GetMessenger();
- prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
+ prop_cstr = tgt->GetComputedProperty(args[2], mf);
if (!prop_cstr) {
prop_cstr = tgt->GetProperty(args[2]);
}
diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx
index 9ac5cd5..89c5b01 100644
--- a/Source/cmGlobVerificationManager.cxx
+++ b/Source/cmGlobVerificationManager.cxx
@@ -8,11 +8,14 @@
#include "cmGeneratedFileStream.h"
#include "cmListFileCache.h"
+#include "cmMessageType.h"
+#include "cmMessenger.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
+bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path,
+ cmMessenger* messenger)
{
if (this->Cache.empty()) {
return true;
@@ -52,7 +55,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
for (auto const& bt : v.Backtraces) {
verifyScriptFile << "# " << std::get<0>(bt);
- std::get<1>(bt).PrintTitle(verifyScriptFile);
+ messenger->PrintBacktraceTitle(verifyScriptFile, std::get<1>(bt));
verifyScriptFile << "\n";
}
@@ -145,7 +148,7 @@ void cmGlobVerificationManager::AddCacheEntry(
const bool recurse, const bool listDirectories, const bool followSymlinks,
const std::string& relative, const std::string& expression,
const std::vector<std::string>& files, const std::string& variable,
- const cmListFileBacktrace& backtrace)
+ const cmListFileBacktrace& backtrace, cmMessenger* messenger)
{
CacheEntryKey key = CacheEntryKey(recurse, listDirectories, followSymlinks,
relative, expression);
@@ -157,17 +160,17 @@ void cmGlobVerificationManager::AddCacheEntry(
} else if (value.Initialized && value.Files != files) {
std::ostringstream message;
message << std::boolalpha;
- message << "The glob expression\n";
+ message << "The glob expression\n ";
key.PrintGlobCommand(message, variable);
- backtrace.PrintTitle(message);
- message << "\nwas already present in the glob cache but the directory\n"
+ message << "\nwas already present in the glob cache but the directory "
"contents have changed during the configuration run.\n";
message << "Matching glob expressions:";
for (auto const& bt : value.Backtraces) {
message << "\n " << std::get<0>(bt);
- std::get<1>(bt).PrintTitle(message);
+ messenger->PrintBacktraceTitle(message, std::get<1>(bt));
}
- cmSystemTools::Error(message.str());
+ messenger->IssueMessage(MessageType::FATAL_ERROR, message.str(),
+ backtrace);
} else {
value.Backtraces.emplace_back(variable, backtrace);
}
diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h
index b618fb0..52d71aa 100644
--- a/Source/cmGlobVerificationManager.h
+++ b/Source/cmGlobVerificationManager.h
@@ -12,6 +12,8 @@
#include "cmListFileCache.h"
+class cmMessenger;
+
/** \class cmGlobVerificationManager
* \brief Class for expressing build-time dependencies on glob expressions.
*
@@ -23,7 +25,7 @@ class cmGlobVerificationManager
protected:
//! Save verification script for given makefile.
//! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake
- bool SaveVerificationScript(const std::string& path);
+ bool SaveVerificationScript(const std::string& path, cmMessenger* messenger);
//! Add an entry into the glob cache
void AddCacheEntry(bool recurse, bool listDirectories, bool followSymlinks,
@@ -31,7 +33,7 @@ protected:
const std::string& expression,
const std::vector<std::string>& files,
const std::string& variable,
- const cmListFileBacktrace& bt);
+ const cmListFileBacktrace& bt, cmMessenger* messenger);
//! Clear the glob cache for state reset.
void Reset();
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index b7bac9c..776ee40 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -2,14 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalBorlandMakefileGenerator.h"
+#include <ostream>
#include <utility>
#include <cm/memory>
#include "cmDocumentationEntry.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmState.h"
#include "cmake.h"
@@ -69,12 +71,13 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ const std::string& config, int /*jobs*/, bool verbose,
+ const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeProgram, projectName, projectDir, targetNames, config, fast,
- cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+ makeProgram, projectName, projectDir, targetNames, config,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, buildOptions, makeOptions);
}
void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice(
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index 5a4e8c2..a280b81 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -4,8 +4,16 @@
#include <iosfwd>
#include <memory>
+#include <string>
+#include <vector>
-#include "cmGlobalNMakeMakefileGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
+
+class cmLocalGenerator;
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
/** \class cmGlobalBorlandMakefileGenerator
* \brief Write a Borland makefiles.
@@ -51,7 +59,8 @@ protected:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 97ad7ab..156ecce 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -38,7 +38,6 @@
#include "cmInstallGenerator.h"
#include "cmInstallRuntimeDependencySet.h"
#include "cmLinkLineComputer.h"
-#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
@@ -329,6 +328,18 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const
return failed;
}
+void cmGlobalGenerator::CheckTargetLinkLibraries() const
+{
+ for (const auto& generator : this->LocalGenerators) {
+ for (const auto& gt : generator->GetGeneratorTargets()) {
+ gt->CheckLinkLibraries();
+ }
+ for (const auto& gt : generator->GetOwnedImportedGeneratorTargets()) {
+ gt->CheckLinkLibraries();
+ }
+ }
+}
+
bool cmGlobalGenerator::CheckTargetsForType() const
{
if (!this->GetLanguageEnabled("Swift")) {
@@ -337,6 +348,12 @@ bool cmGlobalGenerator::CheckTargetsForType() const
bool failed = false;
for (const auto& generator : this->LocalGenerators) {
for (const auto& target : generator->GetGeneratorTargets()) {
+ std::string systemName =
+ target->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ if (systemName.find("Windows") == std::string::npos) {
+ continue;
+ }
+
if (target->GetType() == cmStateEnums::EXECUTABLE) {
std::vector<std::string> const& configs =
target->Makefile->GetGeneratorConfigs(
@@ -1028,6 +1045,54 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
break;
}
}
+
+ if (compilerId == "LCC") {
+ switch (mf->GetPolicyStatus(cmPolicies::CMP0129)) {
+ case cmPolicies::WARN:
+ if (!this->CMakeInstance->GetIsInTryCompile() &&
+ mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0129")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0129) << "\n"
+ "Converting " << lang <<
+ R"( compiler id "LCC" to "GNU" for compatibility.)"
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to convert LCC 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");
+ } else if (lang == "Fortran") {
+ mf->AddDefinition("CMAKE_COMPILER_IS_GNUG77", "1");
+ }
+ {
+ // Fix compiler versions.
+ std::string version = "CMAKE_" + lang + "_COMPILER_VERSION";
+ std::string emulated = "CMAKE_" + lang + "_SIMULATE_VERSION";
+ std::string emulatedId = "CMAKE_" + lang + "_SIMULATE_ID";
+ std::string const& actual = mf->GetRequiredDefinition(emulated);
+ mf->AddDefinition(version, actual);
+ mf->RemoveDefinition(emulatedId);
+ mf->RemoveDefinition(emulated);
+ }
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0129));
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW:
+ // NEW behavior is to keep LCC.
+ break;
+ }
+ }
}
std::string cmGlobalGenerator::GetLanguageOutputExtension(
@@ -1264,7 +1329,7 @@ void cmGlobalGenerator::Configure()
// 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->Makefiles.size()));
+ snprintf(num, sizeof(num), "%d", static_cast<int>(this->Makefiles.size()));
this->GetCMakeInstance()->AddCacheEntry("CMAKE_NUMBER_OF_MAKEFILES", num,
"number of local generators",
cmStateEnums::INTERNAL);
@@ -1553,6 +1618,9 @@ void cmGlobalGenerator::Generate()
this->ExtraGenerator->Generate();
}
+ // Perform validation checks on memoized link structures.
+ this->CheckTargetLinkLibraries();
+
if (!this->CMP0042WarnTargets.empty()) {
std::ostringstream w;
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0042) << "\n";
@@ -1926,16 +1994,19 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
+ cmBuildOptions defaultBuildOptions(false, fast, PackageResolveMode::Disable);
+
return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
- config, false, fast, false, this->TryCompileTimeout);
+ config, defaultBuildOptions, false,
+ this->TryCompileTimeout);
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalGenerator::GenerateBuildCommand(
const std::string& /*unused*/, const std::string& /*unused*/,
const std::string& /*unused*/, std::vector<std::string> const& /*unused*/,
- const std::string& /*unused*/, bool /*unused*/, int /*unused*/,
- bool /*unused*/, std::vector<std::string> const& /*unused*/)
+ const std::string& /*unused*/, int /*unused*/, bool /*unused*/,
+ const cmBuildOptions& /*unused*/, std::vector<std::string> const& /*unused*/)
{
GeneratedMakeCommand makeCommand;
makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented");
@@ -1953,7 +2024,7 @@ int cmGlobalGenerator::Build(
int jobs, const std::string& /*unused*/, const std::string& bindir,
const std::string& projectName, const std::vector<std::string>& targets,
std::string& output, const std::string& makeCommandCSTR,
- const std::string& config, bool clean, bool fast, bool verbose,
+ const std::string& config, const cmBuildOptions& buildOptions, bool verbose,
cmDuration timeout, cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
{
@@ -1985,9 +2056,9 @@ int cmGlobalGenerator::Build(
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
- std::vector<GeneratedMakeCommand> makeCommand =
- this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, targets,
- realConfig, fast, jobs, verbose, nativeOptions);
+ std::vector<GeneratedMakeCommand> makeCommand = this->GenerateBuildCommand(
+ makeCommandCSTR, projectName, bindir, targets, realConfig, jobs, verbose,
+ buildOptions, nativeOptions);
// Workaround to convince some commands to produce output.
if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
@@ -1996,10 +2067,11 @@ int cmGlobalGenerator::Build(
}
// should we do a clean first?
- if (clean) {
+ if (buildOptions.Clean) {
std::vector<GeneratedMakeCommand> cleanCommand =
this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
- { "clean" }, realConfig, fast, jobs, verbose);
+ { "clean" }, realConfig, jobs, verbose,
+ buildOptions);
output += "\nRun Clean Command:";
output += cleanCommand.front().Printable();
output += "\n";
@@ -2824,13 +2896,11 @@ void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
cmTarget& target = tb.first;
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(no_outputs, no_byproducts, no_depends, gti.CommandLines,
- cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str(),
- gti.StdPipesUTF8);
+ cmCustomCommand cc;
+ cc.SetCommandLines(gti.CommandLines);
+ cc.SetWorkingDirectory(gti.WorkingDir.c_str());
+ cc.SetStdPipesUTF8(gti.StdPipesUTF8);
cc.SetUsesTerminal(gti.UsesTerminal);
target.AddPostBuildCommand(std::move(cc));
if (!gti.Message.empty()) {
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 96696aa..a43d4a6 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -20,6 +20,7 @@
#include "cm_codecvt.hxx"
+#include "cmBuildOptions.h"
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmExportSet.h"
@@ -229,8 +230,8 @@ public:
int jobs, const std::string& srcdir, const std::string& bindir,
const std::string& projectName,
std::vector<std::string> const& targetNames, std::string& output,
- const std::string& makeProgram, const std::string& config, bool clean,
- bool fast, bool verbose, cmDuration timeout,
+ const std::string& makeProgram, const std::string& config,
+ const cmBuildOptions& buildOptions, bool verbose, cmDuration timeout,
cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,
std::vector<std::string> const& nativeOptions =
std::vector<std::string>());
@@ -248,7 +249,8 @@ public:
virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions = std::vector<std::string>());
virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
@@ -684,6 +686,7 @@ private:
virtual void ForceLinkerLanguages();
+ void CheckTargetLinkLibraries() const;
bool CheckTargetsForMissingSources() const;
bool CheckTargetsForType() const;
bool CheckTargetsForPchCompilePdb() const;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index b1c0488..5e51dd2 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalGhsMultiGenerator.h"
-#include <algorithm>
#include <map>
#include <ostream>
#include <utility>
@@ -18,6 +17,7 @@
#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -29,10 +29,8 @@
const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
#ifdef __linux__
const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild";
-const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "/usr/ghs";
#elif defined(_WIN32)
const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe";
-const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs";
#endif
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
@@ -70,31 +68,21 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
bool build, cmMakefile* mf)
{
+ /* In build mode nothing to be done.
+ * Toolset already determined and build tool absolute path is cached.
+ */
if (build) {
return true;
}
- std::string tsp; /* toolset path */
+ /* Determine the absolute directory for the toolset */
+ std::string tsp;
this->GetToolset(mf, tsp, ts);
/* no toolset was found */
if (tsp.empty()) {
return false;
}
- if (ts.empty()) {
- std::string message;
- message = cmStrCat(
- "Green Hills MULTI: -T <toolset> not specified; defaulting to \"", tsp,
- '"');
- cmSystemTools::Message(message);
-
- /* store the full toolset for later use
- * -- already done if -T<toolset> was specified
- */
- mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp,
- "Location of generator toolset.",
- cmStateEnums::INTERNAL);
- }
/* set the build tool to use */
std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") +
@@ -102,13 +90,13 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
cmValue prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
/* check if the toolset changed from last generate */
- if (prevTool && (gbuild != *prevTool)) {
- std::string message =
+ if (cmNonempty(prevTool) && !cmSystemTools::ComparePath(gbuild, prevTool)) {
+ std::string const& e =
cmStrCat("toolset build tool: ", gbuild,
- "\nDoes not match the previously used build tool: ", *prevTool,
+ "\nDoes not match the previously used build tool: ", prevTool,
"\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.");
- cmSystemTools::Error(message);
+ mf->IssueMessage(MessageType::FATAL_ERROR, e);
return false;
}
@@ -124,58 +112,20 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
{
- std::string arch;
- if (p.empty()) {
- cmSystemTools::Message(
- "Green Hills MULTI: -A <arch> not specified; defaulting to \"arm\"");
- arch = "arm";
-
- /* store the platform name for later use
- * -- already done if -A<arch> was specified
- */
- mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch,
- "Name of generator platform.",
- cmStateEnums::INTERNAL);
- } else {
- arch = p;
- }
-
- /* check if OS location has been updated by platform scripts */
- std::string platform = mf->GetSafeDefinition("GHS_TARGET_PLATFORM");
- std::string osdir = mf->GetSafeDefinition("GHS_OS_DIR");
- if (cmIsOff(osdir) && platform.find("integrity") != std::string::npos) {
- if (!this->CMakeInstance->GetIsInTryCompile()) {
- /* required OS location is not found */
- std::string m = cmStrCat(
- "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"",
- mf->GetSafeDefinition("GHS_OS_ROOT"), '"');
- cmSystemTools::Message(m);
+ /* set primary target */
+ cmValue t = mf->GetDefinition("GHS_PRIMARY_TARGET");
+ if (cmIsOff(t)) {
+ /* Use the value from `-A` or use `arm` */
+ std::string arch = "arm";
+ if (!cmIsOff(p)) {
+ arch = p;
}
- osdir = "GHS_OS_DIR-NOT-SPECIFIED";
- } else if (!this->CMakeInstance->GetIsInTryCompile() &&
- cmIsOff(this->OsDir) && !cmIsOff(osdir)) {
- /* OS location was updated by auto-selection */
- std::string m = cmStrCat(
- "Green Hills MULTI: GHS_OS_DIR not specified; found \"", osdir, '"');
- cmSystemTools::Message(m);
- }
- this->OsDir = osdir;
-
- // Determine GHS_BSP_NAME
- std::string bspName = mf->GetSafeDefinition("GHS_BSP_NAME");
-
- if (cmIsOff(bspName) && platform.find("integrity") != std::string::npos) {
- bspName = "sim" + arch;
- /* write back the calculate name for next time */
- mf->AddCacheDefinition("GHS_BSP_NAME", bspName,
- "Name of GHS target platform.",
- cmStateEnums::STRING, true);
- std::string m = cmStrCat(
- "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"",
- bspName, '"');
- cmSystemTools::Message(m);
- }
+ cmValue platform = mf->GetDefinition("GHS_TARGET_PLATFORM");
+ std::string tgt = cmStrCat(arch, '_', platform, ".tgt");
+ /* update the primary target name*/
+ mf->AddDefinition("GHS_PRIMARY_TARGET", tgt);
+ }
return true;
}
@@ -186,20 +136,6 @@ void cmGlobalGhsMultiGenerator::EnableLanguage(
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
- const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM")->c_str();
- if (!tgtPlatform) {
- cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
- "specified; defaulting to \"integrity\"");
- tgtPlatform = "integrity";
- }
-
- /* store the platform name for later use */
- mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform,
- "Name of GHS target platform.", cmStateEnums::STRING);
-
- /* store original OS location */
- this->OsDir = mf->GetSafeDefinition("GHS_OS_DIR");
-
this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
@@ -212,43 +148,59 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/)
return true;
}
-void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
+void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsp,
const std::string& ts)
{
- cmValue ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
+ /* Determine tsp - full path of the toolset from ts (toolset hint via -T) */
- if (cmNonempty(ghsRoot)) {
- tsd = *ghsRoot;
- } else {
- tsd = DEFAULT_TOOLSET_ROOT;
- }
+ std::string root = mf->GetSafeDefinition("GHS_TOOLSET_ROOT");
+ // Check if `-T` was set by user
if (ts.empty()) {
+ // Enter toolset search mode
std::vector<std::string> output;
- // Use latest? version
- if (tsd.back() != '/') {
- tsd += "/";
+ // Make sure root exists...
+ if (!cmSystemTools::PathExists(root)) {
+ std::string msg =
+ "GHS_TOOLSET_ROOT directory \"" + root + "\" does not exist.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, msg);
+ tsp = "";
+ return;
+ }
+
+ // Add a directory separator
+ if (root.back() != '/') {
+ root += "/";
}
- cmSystemTools::Glob(tsd, "comp_[^;]+", output);
+
+ // Get all compiler directories in toolset root
+ cmSystemTools::Glob(root, "comp_[^;]+", output);
if (output.empty()) {
+ // No compiler directories found
std::string msg =
- "No GHS toolsets found in GHS_TOOLSET_ROOT \"" + tsd + "\".";
- cmSystemTools::Error(msg);
- tsd = "";
+ "No GHS toolsets found in GHS_TOOLSET_ROOT \"" + root + "\".";
+ mf->IssueMessage(MessageType::FATAL_ERROR, msg);
+ tsp = "";
} else {
- tsd += output.back();
+ // Use latest? version
+ tsp = root + output.back();
}
+
} else {
+ // Toolset was provided by user
std::string tryPath;
- tryPath = cmSystemTools::CollapseFullPath(ts, tsd);
+
+ // NOTE: CollapseFullPath() will determine if user toolset was full path or
+ // or relative path.
+ tryPath = cmSystemTools::CollapseFullPath(ts, root);
if (!cmSystemTools::FileExists(tryPath)) {
- std::string msg = "GHS toolset \"" + tryPath + "\" not found.";
- cmSystemTools::Error(msg);
- tsd = "";
+ std::string msg = "GHS toolset \"" + tryPath + "\" does not exist.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, msg);
+ tsp = "";
} else {
- tsd = tryPath;
+ tsp = tryPath;
}
}
}
@@ -333,25 +285,25 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
fout << "# Top Level Project File\n";
// Specify BSP option if supplied by user
- cmValue bspName =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
+ // -- not all platforms require this entry in the project file
+ cmValue bspName = root->GetMakefile()->GetDefinition("GHS_BSP_NAME");
if (!cmIsOff(bspName)) {
fout << " -bsp " << *bspName << '\n';
}
// Specify OS DIR if supplied by user
// -- not all platforms require this entry in the project file
- if (!cmIsOff(this->OsDir)) {
+ cmValue osDir = root->GetMakefile()->GetDefinition("GHS_OS_DIR");
+ if (!cmIsOff(osDir)) {
cmValue osDirOption =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION");
- std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/');
+ root->GetMakefile()->GetDefinition("GHS_OS_DIR_OPTION");
fout << " ";
if (cmIsOff(osDirOption)) {
fout << "";
} else {
fout << *osDirOption;
}
- fout << "\"" << this->OsDir << "\"\n";
+ fout << "\"" << osDir << "\"\n";
}
}
@@ -558,7 +510,8 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalGhsMultiGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/,
+ const std::string& /*config*/, int jobs, bool /*verbose*/,
+ const cmBuildOptions& /*buildOptions*/,
std::vector<std::string> const& makeOptions)
{
GeneratedMakeCommand makeCommand = {};
@@ -616,8 +569,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
cmLocalGenerator* root)
{
fout << "macro PROJ_NAME=" << root->GetProjectName() << '\n';
- cmValue ghsGpjMacros =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
+ cmValue ghsGpjMacros = root->GetMakefile()->GetDefinition("GHS_GPJ_MACROS");
if (ghsGpjMacros) {
std::vector<std::string> expandedList = cmExpandedList(*ghsGpjMacros);
for (std::string const& arg : expandedList) {
@@ -629,20 +581,8 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
cmLocalGenerator* root, std::ostream& fout)
{
- /* set primary target */
- std::string tgt;
- cmValue t =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
- if (cmNonempty(t)) {
- tgt = *t;
- this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
- } else {
- cmValue a =
- this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
- cmValue p =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
- tgt = cmStrCat((a ? *a : ""), '_', (p ? *p : ""), ".tgt");
- }
+ /* put primary target and customization files into project file */
+ cmValue const tgt = root->GetMakefile()->GetDefinition("GHS_PRIMARY_TARGET");
/* clang-format off */
fout << "primaryTarget=" << tgt << "\n"
@@ -653,7 +593,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
/* clang-format on */
cmValue const customization =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
+ root->GetMakefile()->GetDefinition("GHS_CUSTOMIZATION");
if (cmNonempty(customization)) {
fout << "customization="
<< cmGlobalGhsMultiGenerator::TrimQuotes(*customization) << '\n';
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index bd08301..26ea3c7 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "cmBuildOptions.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmTargetDepend.h"
@@ -87,7 +88,8 @@ protected:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
@@ -112,9 +114,7 @@ private:
static std::string TrimQuotes(std::string str);
- std::string OsDir;
static const char* DEFAULT_BUILD_PROGRAM;
- static const char* DEFAULT_TOOLSET_ROOT;
bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt,
std::vector<cmGeneratorTarget const*>& build);
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 40deebb..1a625cc 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalJOMMakefileGenerator.h"
+#include <ostream>
+
+#include <cmext/algorithm>
+
#include "cmDocumentationEntry.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmake.h"
@@ -59,7 +63,8 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
std::vector<std::string> jomMakeOptions;
@@ -77,6 +82,6 @@ cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
}
return cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
- verbose, jomMakeOptions);
+ makeProgram, projectName, projectDir, targetNames, config, jobs, verbose,
+ buildOptions, jomMakeOptions);
}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 58860dd..332d1cf 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -4,8 +4,16 @@
#include <iosfwd>
#include <memory>
+#include <string>
+#include <vector>
+#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmValue.h"
+
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
/** \class cmGlobalJOMMakefileGenerator
* \brief Write a JOM makefiles.
@@ -44,7 +52,8 @@ protected:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index ae9d5a7..c8520b8 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -5,10 +5,10 @@
#include "cmsys/FStream.hxx"
#include "cmDocumentationEntry.h"
-#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmake.h"
cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm)
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index 1a47b4f..586487f 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -3,9 +3,16 @@
#pragma once
#include <memory>
+#include <string>
+#include <vector>
+#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
+
/** \class cmGlobalMSYSMakefileGenerator
* \brief Write a NMake makefiles.
*
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index d9fc505..54d048d 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -3,9 +3,9 @@
#include "cmGlobalMinGWMakefileGenerator.h"
#include "cmDocumentationEntry.h"
-#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmSystemTools.h"
#include "cmake.h"
cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm)
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index ffc9ebe..1574faf 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -3,9 +3,16 @@
#pragma once
#include <memory>
+#include <string>
+#include <vector>
+#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
+
/** \class cmGlobalMinGWMakefileGenerator
* \brief Write a NMake makefiles.
*
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index a038f87..55748cf 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -2,13 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalNMakeMakefileGenerator.h"
+#include <ostream>
+
+#include <cmext/algorithm>
+
#include "cmsys/RegularExpression.hxx"
#include "cmDocumentationEntry.h"
#include "cmDuration.h"
-#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmake.h"
cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
@@ -99,7 +106,8 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ const std::string& config, int /*jobs*/, bool verbose,
+ const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
std::vector<std::string> nmakeMakeOptions;
@@ -110,8 +118,8 @@ cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
cm::append(nmakeMakeOptions, makeOptions);
return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeProgram, projectName, projectDir, targetNames, config, fast,
- cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
+ makeProgram, projectName, projectDir, targetNames, config,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, buildOptions, nmakeMakeOptions);
}
void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 4f202b5..b3574eb 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -4,8 +4,18 @@
#include <iosfwd>
#include <memory>
+#include <string>
+#include <vector>
+#include "cm_codecvt.hxx"
+
+#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmValue.h"
+
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
/** \class cmGlobalNMakeMakefileGenerator
* \brief Write a NMake makefiles.
@@ -48,7 +58,8 @@ protected:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7122b9f..4245037 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -156,7 +156,7 @@ std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
encoded += i;
} else {
char buf[16];
- sprintf(buf, ".%02x", static_cast<unsigned int>(i));
+ snprintf(buf, sizeof(buf), ".%02x", static_cast<unsigned int>(i));
encoded += buf;
}
}
@@ -166,14 +166,18 @@ std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
std::string result = lit;
- cmSystemTools::ReplaceString(result, "$", "$$");
- cmSystemTools::ReplaceString(result, "\n", "$\n");
+ EncodeLiteralInplace(result);
+ return result;
+}
+
+void cmGlobalNinjaGenerator::EncodeLiteralInplace(std::string& lit)
+{
+ cmSystemTools::ReplaceString(lit, "$", "$$");
+ cmSystemTools::ReplaceString(lit, "\n", "$\n");
if (this->IsMultiConfig()) {
- cmSystemTools::ReplaceString(result,
- cmStrCat('$', this->GetCMakeCFGIntDir()),
+ cmSystemTools::ReplaceString(lit, cmStrCat('$', this->GetCMakeCFGIntDir()),
this->GetCMakeCFGIntDir());
}
- return result;
}
std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
@@ -185,7 +189,7 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
else
std::replace(result.begin(), result.end(), '/', '\\');
#endif
- result = this->EncodeLiteral(result);
+ this->EncodeLiteralInplace(result);
cmSystemTools::ReplaceString(result, " ", "$ ");
cmSystemTools::ReplaceString(result, ":", "$:");
return result;
@@ -955,7 +959,7 @@ cmGlobalNinjaGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& /*projectName*/,
const std::string& /*projectDir*/,
std::vector<std::string> const& targetNames, const std::string& config,
- bool /*fast*/, int jobs, bool verbose,
+ int jobs, bool verbose, const cmBuildOptions& /*buildOptions*/,
std::vector<std::string> const& makeOptions)
{
GeneratedMakeCommand makeCommand;
@@ -1021,6 +1025,19 @@ bool cmGlobalNinjaGenerator::OpenBuildFileStreams()
return false;
}
+ // New buffer size 8 MiB
+ constexpr auto buildFileStreamBufferSize = 8 * 1024 * 1024;
+
+ // Ensure the buffer is allocated
+ if (!this->BuildFileStreamBuffer) {
+ this->BuildFileStreamBuffer =
+ cm::make_unique<char[]>(buildFileStreamBufferSize);
+ }
+
+ // Enlarge the internal buffer of the `BuildFileStream`
+ this->BuildFileStream->rdbuf()->pubsetbuf(this->BuildFileStreamBuffer.get(),
+ buildFileStreamBufferSize);
+
// Write a comment about this file.
*this->BuildFileStream
<< "# This file contains all the build statements describing the\n"
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 84fc06c..aa2df4d 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -18,6 +18,7 @@
#include "cm_codecvt.hxx"
+#include "cmBuildOptions.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
@@ -77,6 +78,7 @@ public:
static std::string EncodeRuleName(std::string const& name);
std::string EncodeLiteral(const std::string& lit);
+ void EncodeLiteralInplace(std::string& lit);
std::string EncodePath(const std::string& path);
std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
@@ -199,7 +201,8 @@ public:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
@@ -526,6 +529,7 @@ private:
/// The file containing the build statement. (the relationship of the
/// compilation DAG).
std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
+ std::unique_ptr<char[]> BuildFileStreamBuffer;
/// The file containing the rule statements. (The action attached to each
/// edge of the compilation DAG).
std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 0556540..ab9ca50 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -518,7 +518,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
const std::string& makeProgram, const std::string& /*projectName*/,
const std::string& /*projectDir*/,
std::vector<std::string> const& targetNames, const std::string& /*config*/,
- bool fast, int jobs, bool verbose,
+ int jobs, bool verbose, const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
GeneratedMakeCommand makeCommand;
@@ -548,7 +548,7 @@ cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
makeCommand.Add(makeOptions.begin(), makeOptions.end());
for (auto tname : targetNames) {
if (!tname.empty()) {
- if (fast) {
+ if (buildOptions.Fast) {
tname += "/fast";
}
cmSystemTools::ConvertToOutputSlashes(tname);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 94ee476..5157826 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -12,6 +12,7 @@
#include <string>
#include <vector>
+#include "cmBuildOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
@@ -163,7 +164,8 @@ public:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 6cab492..db54b86 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -3,24 +3,35 @@
#include "cmGlobalVisualStudio10Generator.h"
#include <algorithm>
+#include <cstring>
+#include <map>
+#include <sstream>
#include <utility>
#include <cm/memory>
#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
-#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudio71Generator.h"
+#include "cmGlobalVisualStudio7Generator.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmIDEFlagTable.h"
+#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmVisualStudioSlnData.h"
#include "cmVisualStudioSlnParser.h"
@@ -159,7 +170,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
this->DefaultNasmFlagTableName = "v10";
this->DefaultRCFlagTableName = "v10";
- this->Version = VS10;
+ this->Version = VSVersion::VS10;
this->PlatformToolsetNeedsDebugEnum = false;
}
@@ -266,8 +277,8 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
}
this->SupportsUnityBuilds =
- this->Version >= cmGlobalVisualStudioGenerator::VS16 ||
- (this->Version == cmGlobalVisualStudioGenerator::VS15 &&
+ this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 ||
+ (this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS15 &&
cmSystemTools::PathExists(this->VCTargetsPath +
"/Microsoft.Cpp.Unity.targets"));
@@ -580,7 +591,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf)
this->DefaultPlatformToolset = this->SelectWindowsCEToolset();
- if (this->GetVersion() == cmGlobalVisualStudioGenerator::VS12) {
+ if (this->GetVersion() == cmGlobalVisualStudioGenerator::VSVersion::VS12) {
// VS 12 .NET CF defaults to .NET framework 3.9 for Windows CE.
this->DefaultTargetFrameworkVersion = "v3.9";
this->DefaultTargetFrameworkIdentifier = "WindowsEmbeddedCompact";
@@ -713,6 +724,10 @@ void cmGlobalVisualStudio10Generator::Generate()
/* clang-format on */
lg->IssueMessage(MessageType::WARNING, e.str());
}
+ if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
+ "CMAKE_VS_NUGET_PACKAGE_RESTORE")) {
+ this->CMakeInstance->MarkCliAsUsed("CMAKE_VS_NUGET_PACKAGE_RESTORE");
+ }
}
void cmGlobalVisualStudio10Generator::EnableLanguage(
@@ -1088,7 +1103,8 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalVisualStudio10Generator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
std::vector<GeneratedMakeCommand> makeCommands;
@@ -1118,7 +1134,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
slnFile += ".sln";
cmVisualStudioSlnParser parser;
if (parser.ParseFile(slnFile, slnData,
- cmVisualStudioSlnParser::DataGroupProjects)) {
+ cmVisualStudioSlnParser::DataGroupAll)) {
std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
for (cmSlnProjectEntry const& project : slnProjects) {
if (useDevEnv) {
@@ -1134,8 +1150,8 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
if (useDevEnv) {
// Use devenv to build solutions containing Intel Fortran projects.
return cmGlobalVisualStudio7Generator::GenerateBuildCommand(
- makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
- verbose, makeOptions);
+ makeProgram, projectName, projectDir, targetNames, config, jobs, verbose,
+ buildOptions, makeOptions);
}
std::vector<std::string> realTargetNames = targetNames;
@@ -1154,37 +1170,108 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
GeneratedMakeCommand makeCommand;
makeCommand.RequiresOutputForward = requiresOutputForward;
makeCommand.Add(makeProgramSelected);
+ cm::optional<cmSlnProjectEntry> proj = cm::nullopt;
if (tname == "clean") {
- makeCommand.Add(std::string(projectName) + ".sln");
+ makeCommand.Add(cmStrCat(projectName, ".sln"));
makeCommand.Add("/t:Clean");
} else {
std::string targetProject = cmStrCat(tname, ".vcxproj");
+ proj = slnData.GetProjectByName(tname);
if (targetProject.find('/') == std::string::npos) {
// it might be in a subdir
- if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
+ if (proj) {
targetProject = proj->GetRelativePath();
cmSystemTools::ConvertToUnixSlashes(targetProject);
}
}
- makeCommand.Add(std::move(targetProject));
+ makeCommand.Add(targetProject);
+
+ // Check if we do need a restore at all (i.e. if there are package
+ // references and restore has not been disabled by a command line option.
+ PackageResolveMode restoreMode = buildOptions.ResolveMode;
+ bool requiresRestore = true;
+
+ if (restoreMode == PackageResolveMode::Disable) {
+ requiresRestore = false;
+ } else if (cmValue cached =
+ this->CMakeInstance->GetState()->GetCacheEntryValue(
+ tname + "_REQUIRES_VS_PACKAGE_RESTORE")) {
+ requiresRestore = cached.IsOn();
+ } else {
+ // There are no package references defined.
+ requiresRestore = false;
+ }
+
+ // If a restore is required, evaluate the restore mode.
+ if (requiresRestore) {
+ if (restoreMode == PackageResolveMode::OnlyResolve) {
+ // Only invoke the restore target on the project.
+ makeCommand.Add("/t:Restore");
+ } else {
+ // Invoke restore target, unless it has been explicitly disabled.
+ bool restorePackages = true;
+
+ if (this->Version < VSVersion::VS15) {
+ // Package restore is only supported starting from Visual Studio
+ // 2017. Package restore must be executed manually using NuGet
+ // shell for older versions.
+ this->CMakeInstance->IssueMessage(
+ MessageType::WARNING,
+ "Restoring package references is only supported for Visual "
+ "Studio 2017 and later. You have to manually restore the "
+ "packages using NuGet before building the project.");
+ restorePackages = false;
+ } else if (restoreMode == PackageResolveMode::Default) {
+ // Decide if a restore is performed, based on a cache variable.
+ if (cmValue cached =
+ this->CMakeInstance->GetState()->GetCacheEntryValue(
+ "CMAKE_VS_NUGET_PACKAGE_RESTORE"))
+ restorePackages = cached.IsOn();
+ }
+
+ if (restorePackages) {
+ if (this->IsMsBuildRestoreSupported()) {
+ makeCommand.Add("/restore");
+ } else {
+ GeneratedMakeCommand restoreCommand;
+ restoreCommand.Add(makeProgramSelected);
+ restoreCommand.Add(targetProject);
+ restoreCommand.Add("/t:Restore");
+ makeCommands.emplace_back(restoreCommand);
+ }
+ }
+ }
+ }
}
- std::string configArg = "/p:Configuration=";
- if (!config.empty()) {
- configArg += config;
- } else {
- configArg += "Debug";
+
+ std::string plainConfig = config;
+ if (config.empty()) {
+ plainConfig = "Debug";
+ }
+
+ std::string platform = GetPlatformName();
+ if (proj) {
+ std::string extension =
+ cmSystemTools::GetFilenameLastExtension(proj->GetRelativePath());
+ extension = cmSystemTools::LowerCase(extension);
+ if (extension.compare(".csproj") == 0) {
+ // Use correct platform name
+ platform =
+ slnData.GetConfigurationTarget(tname, plainConfig, platform);
+ }
}
- makeCommand.Add(configArg);
- makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName());
- makeCommand.Add(std::string("/p:VisualStudioVersion=") +
- this->GetIDEVersion());
+
+ makeCommand.Add(cmStrCat("/p:Configuration=", plainConfig));
+ makeCommand.Add(cmStrCat("/p:Platform=", platform));
+ makeCommand.Add(
+ cmStrCat("/p:VisualStudioVersion=", this->GetIDEVersion()));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
makeCommand.Add("/m");
} else {
- makeCommand.Add(std::string("/m:") + std::to_string(jobs));
+ makeCommand.Add(cmStrCat("/m:", std::to_string(jobs)));
}
// Having msbuild.exe and cl.exe using multiple jobs is discouraged
makeCommand.Add("/p:CL_MPCount=1");
@@ -1192,7 +1279,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
// Respect the verbosity: 'n' normal will show build commands
// 'm' minimal only the build step's title
- makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m"));
+ makeCommand.Add(cmStrCat("/v:", ((verbose) ? "n" : "m")));
makeCommand.Add(makeOptions.begin(), makeOptions.end());
makeCommands.emplace_back(std::move(makeCommand));
}
@@ -1273,23 +1360,23 @@ std::string cmGlobalVisualStudio10Generator::Encoding()
const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const
{
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VS9:
- case cmGlobalVisualStudioGenerator::VS10:
- case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "4.0";
// in Visual Studio 2013 they detached the MSBuild tools version
// from the .Net Framework version and instead made it have it's own
// version number
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "12.0";
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return "14.0";
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
return "15.0";
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
return "16.0";
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return "17.0";
}
return "";
@@ -1548,6 +1635,18 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM");
}
+bool cmGlobalVisualStudio10Generator::IsMsBuildRestoreSupported() const
+{
+ if (this->Version >= VSVersion::VS16) {
+ return true;
+ }
+
+ static std::string const vsVer15_7_5 = "15.7.27703.2042";
+ cm::optional<std::string> vsVer = this->GetVSInstanceVersion();
+ return (vsVer &&
+ cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer15_7_5));
+}
+
std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const
{
std::string const& toolset = this->GetPlatformToolsetString();
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 6e62390..4977a84 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -2,14 +2,25 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <cstddef>
#include <memory>
#include <set>
+#include <string>
+#include <vector>
#include <cm/optional>
#include <cm/string_view>
#include "cmGlobalVisualStudio8Generator.h"
+class cmGeneratorTarget;
+class cmGlobalGeneratorFactory;
+class cmLocalGenerator;
+class cmMakefile;
+class cmSourceFile;
+class cmake;
+struct cmIDEFlagTable;
+
/** \class cmGlobalVisualStudio10Generator
* \brief Write a Unix makefiles.
*
@@ -32,7 +43,8 @@ public:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
@@ -161,6 +173,8 @@ public:
cmIDEFlagTable const* GetMasmFlagTable() const;
cmIDEFlagTable const* GetNasmFlagTable() const;
+ bool IsMsBuildRestoreSupported() const;
+
protected:
cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name,
std::string const& platformInGeneratorName);
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index a5ffcf0..10dc258 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -2,12 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio11Generator.h"
+#include <cstring>
+#include <sstream>
#include <utility>
+#include <vector>
-#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio10Generator.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudioGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
static const char vs11generatorName[] = "Visual Studio 11 2012";
@@ -141,7 +148,7 @@ cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
this->DefaultLinkFlagTableName = "v11";
this->DefaultMasmFlagTableName = "v11";
this->DefaultRCFlagTableName = "v11";
- this->Version = VS11;
+ this->Version = VSVersion::VS11;
}
bool cmGlobalVisualStudio11Generator::MatchesGeneratorName(
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index b11905e..2f8a7f6 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -4,13 +4,14 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
#include <memory>
#include <set>
#include <string>
+#include <cm/optional>
+
#include "cmGlobalVisualStudio10Generator.h"
-#include "cmStateTypes.h"
+#include "cmTransformDepfile.h"
class cmGlobalGeneratorFactory;
class cmMakefile;
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 8bdf356..12ffa5b 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -2,10 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio12Generator.h"
-#include "cmAlgorithms.h"
+#include <cstring>
+#include <sstream>
+#include <vector>
+
#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio10Generator.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudioGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
static const char vs12generatorName[] = "Visual Studio 12 2013";
@@ -114,7 +122,7 @@ cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
this->DefaultLinkFlagTableName = "v12";
this->DefaultMasmFlagTableName = "v12";
this->DefaultRCFlagTableName = "v12";
- this->Version = VS12;
+ this->Version = VSVersion::VS12;
}
bool cmGlobalVisualStudio12Generator::MatchesGeneratorName(
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index c220d40..a84756e 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -4,7 +4,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
#include <memory>
#include <string>
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index ff1642f..9f94cca 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -2,11 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio14Generator.h"
+#include <cstring>
+#include <sstream>
+
#include <cm/vector>
#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio10Generator.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudioGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmValue.h"
static const char vs14generatorName[] = "Visual Studio 14 2015";
@@ -116,7 +125,7 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
this->DefaultLinkFlagTableName = "v140";
this->DefaultMasmFlagTableName = "v14";
this->DefaultRCFlagTableName = "v14";
- this->Version = VS14;
+ this->Version = VSVersion::VS14;
}
bool cmGlobalVisualStudio14Generator::MatchesGeneratorName(
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index 7804b83..7fb9b4b 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -4,7 +4,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
#include <memory>
#include <string>
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 50975ff..ce943a2 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -2,11 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio71Generator.h"
-#include "cmDocumentationEntry.h"
+#include <map>
+#include <sstream>
+
#include "cmGeneratorTarget.h"
-#include "cmLocalVisualStudio7Generator.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+class cmake;
cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
cmake* cm, const std::string& platformName)
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index cb3b8c1..0e7ddd0 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -2,7 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
#include "cmGlobalVisualStudio7Generator.h"
+#include "cmValue.h"
+
+class cmGeneratorTarget;
+class cmLocalGenerator;
+class cmake;
+template <typename T>
+class BT;
/** \class cmGlobalVisualStudio71Generator
* \brief Write a Unix makefiles.
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 6876e61..134937e 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -2,6 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio7Generator.h"
+#include <algorithm>
+#include <cstdio>
+#include <ostream>
#include <utility>
#include <vector>
@@ -10,19 +13,22 @@
#include <windows.h>
-#include <assert.h>
-
-#include "cmsys/Encoding.hxx"
-
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
#include "cmUuid.h"
+#include "cmVisualStudioGeneratorOptions.h"
#include "cmake.h"
static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
@@ -206,7 +212,7 @@ cmGlobalVisualStudio7Generator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& /*projectDir*/,
std::vector<std::string> const& targetNames, const std::string& config,
- bool /*fast*/, int /*jobs*/, bool /*verbose*/,
+ int /*jobs*/, bool /*verbose*/, const cmBuildOptions& /*buildOptions*/,
std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
@@ -298,7 +304,8 @@ void cmGlobalVisualStudio7Generator::Generate()
GetSLNFile(this->LocalGenerators[0].get()));
}
- if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) {
+ if (this->Version == VSVersion::VS10 &&
+ !this->CMakeInstance->GetIsInTryCompile()) {
std::string cmakeWarnVS10;
if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
"CMAKE_WARN_VS10")) {
@@ -367,8 +374,16 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
this->IsPartOfDefaultBuild(configs, projectTargets, target);
cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName) {
+ std::string mapping;
+
+ // On VS 19 and above, always map .NET SDK projects to "Any CPU".
+ if (target->IsDotNetSdkTarget() &&
+ this->GetVersion() >= VSVersion::VS16 &&
+ !this->IsReservedTarget(target->GetName())) {
+ mapping = "Any CPU";
+ }
this->WriteProjectConfigurations(fout, *vcprojName, *target, configs,
- configsPartOfDefaultBuild);
+ configsPartOfDefaultBuild, mapping);
}
}
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 8e762cf..33f1063 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -2,14 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <iosfwd>
+#include <map>
#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm3p/json/value.h>
-#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
#include "cmValue.h"
-class cmTarget;
+class cmGeneratorTarget;
struct cmIDEFlagTable;
+class cmLocalGenerator;
+class cmMakefile;
+class cmake;
+template <typename T>
+class BT;
/** \class cmGlobalVisualStudio7Generator
* \brief Write a Unix makefiles.
@@ -57,7 +69,8 @@ public:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 1e45813..dbd2de9 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -2,22 +2,41 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio8Generator.h"
+#include <algorithm>
+#include <functional>
+#include <ostream>
+#include <utility>
+
#include <cm/memory>
+#include <cmext/algorithm>
#include <cmext/memory>
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmDocumentationEntry.h"
+#include "cmCustomCommandTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalVisualStudio7Generator.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmSourceFile.h"
-#include "cmVisualStudioWCEPlatformParser.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
+#include "cmValue.h"
+#include "cmVisualStudioGeneratorOptions.h"
#include "cmake.h"
+struct cmIDEFlagTable;
+
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
cmake* cm, const std::string& name,
std::string const& platformInGeneratorName)
@@ -147,13 +166,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
auto& lg =
cm::static_reference_cast<cmLocalVisualStudio7Generator>(generators[0]);
- const char* no_working_directory = nullptr;
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
- cmCustomCommandLines no_commands;
- cmTarget* tgt = lg.AddUtilityCommand(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, no_working_directory,
- no_byproducts, no_depends, no_commands, cmPolicies::NEW);
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
+ std::move(cc));
auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg);
auto gt = ptr.get();
@@ -203,11 +219,15 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
std::vector<std::string> byproducts;
byproducts.push_back(cm->GetGlobVerifyStamp());
- lg.AddCustomCommandToTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts,
- no_depends, verifyCommandLines,
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetByproducts(byproducts);
+ cc->SetCommandLines(verifyCommandLines);
+ cc->SetComment("Checking File Globs");
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetStdPipesUTF8(stdPipesUTF8);
+ lg.AddCustomCommandToTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET,
cmCustomCommandType::PRE_BUILD,
- "Checking File Globs", no_working_directory,
- cmPolicies::NEW, stdPipesUTF8);
+ std::move(cc));
// Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
// otherwise the prebuild command will not be run.
@@ -234,13 +254,16 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// 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;
- cmImplicitDependsList no_implicit_depends;
- if (cmSourceFile* file = lg.AddCustomCommandToOutput(
- stamps, no_byproducts, listFiles, no_main_dependency,
- no_implicit_depends, commandLines, "Checking Build System",
- no_working_directory, cmPolicies::NEW, true, false, false, false, "",
- "", stdPipesUTF8)) {
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(stamps);
+ cc->SetDepends(listFiles);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment("Checking Build System");
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetStdPipesUTF8(stdPipesUTF8);
+ if (cmSourceFile* file =
+ lg.AddCustomCommandToOutput(std::move(cc), true)) {
gt->AddSource(file->ResolveFullPath());
} else {
cmSystemTools::Error("Error adding rule for " + stamps[0]);
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index b6ecdf0..fe57c54 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -2,10 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <vector>
+
#include <cm/optional>
#include "cmGlobalVisualStudio71Generator.h"
+class cmGeneratorTarget;
+class cmMakefile;
+class cmake;
+struct cmIDEFlagTable;
+
/** \class cmGlobalVisualStudio8Generator
* \brief Write a Unix makefiles.
*
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 2339a80..e03e665 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -2,14 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio9Generator.h"
+#include <cstring>
#include <utility>
+#include <vector>
#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmMakefile.h"
-#include "cmMessageType.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmSystemTools.h"
#include "cmVisualStudioWCEPlatformParser.h"
+class cmake;
+
static const char vs9generatorName[] = "Visual Studio 9 2008";
class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory
@@ -119,7 +124,7 @@ cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
std::string const& platformInGeneratorName)
: cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName)
{
- this->Version = VS9;
+ this->Version = VSVersion::VS9;
std::string vc9Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\9.0\\Setup\\VC;"
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index 6f4d159..1c93d49 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -3,9 +3,13 @@
#pragma once
#include <memory>
+#include <string>
#include "cmGlobalVisualStudio8Generator.h"
+class cmGlobalGeneratorFactory;
+class cmake;
+
/** \class cmGlobalVisualStudio9Generator
* \brief Write a Unix makefiles.
*
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index f9bd67e..141b5eb 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -3,8 +3,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudioGenerator.h"
+#include <cassert>
#include <future>
#include <iostream>
+#include <sstream>
+#include <system_error>
+#include <utility>
#include <cm/iterator>
#include <cm/memory>
@@ -14,17 +18,20 @@
#include <objbase.h>
#include <shellapi.h>
-#include "cmsys/Encoding.hxx"
-
#include "cmCallVisualStudioMacro.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
-#include "cmLocalVisualStudioGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
@@ -90,21 +97,21 @@ std::string const& cmGlobalVisualStudioGenerator::GetPlatformName() const
const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const
{
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return "9.0";
- case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
return "10.0";
- case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "11.0";
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "12.0";
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return "14.0";
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
return "15.0";
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
return "16.0";
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return "17.0";
}
return "";
@@ -117,11 +124,11 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << '\n';
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n";
fout << "# Visual Studio 2008\n";
break;
- case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
if (this->ExpressEdition) {
fout << "# Visual C++ Express 2010\n";
@@ -129,7 +136,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 2010\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
fout << "# Visual Studio Express 2012 for Windows Desktop\n";
@@ -137,7 +144,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 2012\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
fout << "# Visual Studio Express 2013 for Windows Desktop\n";
@@ -145,7 +152,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 2013\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
// Visual Studio 14 writes .sln format 12.00
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
@@ -154,7 +161,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 14\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
// Visual Studio 15 writes .sln format 12.00
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
@@ -163,7 +170,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio 15\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
// Visual Studio 16 writes .sln format 12.00
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
@@ -172,7 +179,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
fout << "# Visual Studio Version 16\n";
}
break;
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
// Visual Studio 17 writes .sln format 12.00
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
if (this->ExpressEdition) {
@@ -199,19 +206,18 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
{
// Add a special target that depends on ALL projects for easy build
// of one configuration only.
- const char* no_working_dir = nullptr;
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
- cmCustomCommandLines no_commands;
for (auto const& it : this->ProjectMap) {
std::vector<cmLocalGenerator*> const& gen = it.second;
// add the ALL_BUILD to the first local generator of each project
if (!gen.empty()) {
// Use no actual command lines so that the target itself is not
// considered always out of date.
- cmTarget* allBuild = gen[0]->AddUtilityCommand(
- "ALL_BUILD", true, no_working_dir, no_byproducts, no_depends,
- no_commands, cmPolicies::NEW, false, "Build all projects");
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetComment("Build all projects");
+ cmTarget* allBuild =
+ gen[0]->AddUtilityCommand("ALL_BUILD", true, std::move(cc));
gen[0]->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(allBuild, gen[0]));
@@ -942,9 +948,13 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
{ cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file });
- cmCustomCommand command(outputs, empty, empty, commandLines,
- gt->Target->GetMakefile()->GetBacktrace(),
- "Auto build dll exports", ".", true);
+ cmCustomCommand command;
+ command.SetOutputs(outputs);
+ command.SetCommandLines(commandLines);
+ command.SetComment("Auto build dll exports");
+ command.SetBacktrace(gt->Target->GetMakefile()->GetBacktrace());
+ command.SetWorkingDirectory(".");
+ command.SetStdPipesUTF8(true);
commands.push_back(std::move(command));
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 23c8a02..cb1b14b 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -10,8 +10,11 @@
#include <string>
#include <vector>
+#include "cm_codecvt.hxx"
+
#include "cmGlobalGenerator.h"
#include "cmTargetDepend.h"
+#include "cmValue.h"
class cmCustomCommand;
class cmGeneratorTarget;
@@ -29,7 +32,7 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator
{
public:
/** Known versions of Visual Studio. */
- enum VSVersion
+ enum class VSVersion : uint16_t
{
VS9 = 90,
VS10 = 100,
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index b5a6b9f..bc38335 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -2,16 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudioVersionedGenerator.h"
+#include <cstring>
+#include <set>
+#include <sstream>
+#include <utility>
+#include <vector>
+
#include <cmext/string_view>
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
-#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio10Generator.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmVSSetupHelper.h"
#include "cmake.h"
@@ -65,21 +75,21 @@ static unsigned int VSVersionToMajor(
cmGlobalVisualStudioGenerator::VSVersion v)
{
switch (v) {
- case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return 9;
- case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
return 10;
- case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return 11;
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return 12;
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return 14;
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
return 15;
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
return 16;
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return 17;
}
return 0;
@@ -89,40 +99,64 @@ static const char* VSVersionToToolset(
cmGlobalVisualStudioGenerator::VSVersion v)
{
switch (v) {
- case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
return "v90";
- case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
return "v100";
- case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
return "v110";
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "v120";
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return "v140";
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
return "v141";
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
return "v142";
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return "v143";
}
return "";
}
+static std::string VSVersionToMajorString(
+ cmGlobalVisualStudioGenerator::VSVersion v)
+{
+ switch (v) {
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
+ return "9";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ return "10";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
+ return "11";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
+ return "12";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
+ return "14";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
+ return "15";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
+ return "16";
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
+ return "17";
+ }
+ return "";
+}
+
static const char* VSVersionToAndroidToolset(
cmGlobalVisualStudioGenerator::VSVersion v)
{
switch (v) {
- case cmGlobalVisualStudioGenerator::VS9:
- case cmGlobalVisualStudioGenerator::VS10:
- case cmGlobalVisualStudioGenerator::VS11:
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "";
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return "Clang_3_8";
- case cmGlobalVisualStudioGenerator::VS15:
- case cmGlobalVisualStudioGenerator::VS16:
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return "Clang_5_0";
}
return "";
@@ -160,7 +194,7 @@ public:
if (!*p) {
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudioVersionedGenerator(
- cmGlobalVisualStudioGenerator::VS15, cm, genName, ""));
+ cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName, ""));
}
if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
@@ -168,12 +202,12 @@ public:
if (strcmp(p, "Win64") == 0) {
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudioVersionedGenerator(
- cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64"));
+ cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName, "x64"));
}
if (strcmp(p, "ARM") == 0) {
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudioVersionedGenerator(
- cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM"));
+ cmGlobalVisualStudioGenerator::VSVersion::VS15, cm, genName, "ARM"));
}
return std::unique_ptr<cmGlobalGenerator>();
}
@@ -269,7 +303,7 @@ public:
if (!*p) {
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudioVersionedGenerator(
- cmGlobalVisualStudioGenerator::VS16, cm, genName, ""));
+ cmGlobalVisualStudioGenerator::VSVersion::VS16, cm, genName, ""));
}
return std::unique_ptr<cmGlobalGenerator>();
}
@@ -334,7 +368,7 @@ public:
if (!*p) {
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudioVersionedGenerator(
- cmGlobalVisualStudioGenerator::VS17, cm, genName, ""));
+ cmGlobalVisualStudioGenerator::VSVersion::VS17, cm, genName, ""));
}
return std::unique_ptr<cmGlobalGenerator>();
}
@@ -397,11 +431,11 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
this->DefaultCLFlagTableName = VSVersionToToolset(this->Version);
this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version);
this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version);
- if (this->Version >= cmGlobalVisualStudioGenerator::VS16) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16) {
this->DefaultPlatformName = VSHostPlatformName();
this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture();
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS17) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {
// FIXME: Search for an existing framework? Under '%ProgramFiles(x86)%',
// see 'Reference Assemblies\Microsoft\Framework\.NETFramework'.
// Use a version installed by VS 2022 without a separate component.
@@ -414,23 +448,23 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
{
std::string genName;
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VS9:
- case cmGlobalVisualStudioGenerator::VS10:
- case cmGlobalVisualStudioGenerator::VS11:
- case cmGlobalVisualStudioGenerator::VS12:
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
break;
- case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
if (cmVS15GenName(name, genName)) {
return genName == this->GetName();
}
break;
- case cmGlobalVisualStudioGenerator::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
if (cmVS16GenName(name, genName)) {
return genName == this->GetName();
}
break;
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
if (cmVS17GenName(name, genName)) {
return genName == this->GetName();
}
@@ -447,15 +481,25 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
return true;
}
- if (!i.empty()) {
- if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
+ if (!this->ParseGeneratorInstance(i, mf)) {
+ return false;
+ }
+
+ if (!this->GeneratorInstanceVersion.empty()) {
+ std::string const majorStr = VSVersionToMajorString(this->Version);
+ cmsys::RegularExpression versionRegex(
+ cmStrCat("^", majorStr, "\\.[0-9]+\\.[0-9]+\\.[0-9]+$"));
+ if (!versionRegex.find(this->GeneratorInstanceVersion)) {
std::ostringstream e;
/* clang-format off */
e <<
"Generator\n"
" " << this->GetName() << "\n"
- "could not find specified instance of Visual Studio:\n"
- " " << i;
+ "given instance specification\n"
+ " " << i << "\n"
+ "but the version field is not 4 integer components"
+ " starting in " << majorStr << "."
+ ;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
@@ -463,7 +507,29 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
}
std::string vsInstance;
- if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
+ if (!i.empty()) {
+ vsInstance = i;
+ if (!this->vsSetupAPIHelper.SetVSInstance(
+ this->GeneratorInstance, this->GeneratorInstanceVersion)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "could not find specified instance of Visual Studio:\n"
+ " " << i;
+ /* clang-format on */
+ if (!this->GeneratorInstance.empty() &&
+ this->GeneratorInstanceVersion.empty() &&
+ cmSystemTools::FileIsDirectory(this->GeneratorInstance)) {
+ e << "\n"
+ "The directory exists, but the instance is not known to the "
+ "Visual Studio Installer, and no 'version=' field was given.";
+ }
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+ } else if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
std::ostringstream e;
/* clang-format off */
e <<
@@ -491,6 +557,88 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
return true;
}
+bool cmGlobalVisualStudioVersionedGenerator::ParseGeneratorInstance(
+ std::string const& is, cmMakefile* mf)
+{
+ this->GeneratorInstance.clear();
+ this->GeneratorInstanceVersion.clear();
+
+ std::vector<std::string> const fields = cmTokenize(is, ",");
+ std::vector<std::string>::const_iterator fi = fields.begin();
+ if (fi == fields.end()) {
+ return true;
+ }
+
+ // The first field may be the VS instance.
+ if (fi->find('=') == fi->npos) {
+ this->GeneratorInstance = *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 instance specification\n"
+ " " << is << "\n"
+ "that contains a field after the first ',' with no '='."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::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 instance specification\n"
+ " " << is << "\n"
+ "that contains duplicate field key '" << key << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+ if (!this->ProcessGeneratorInstanceField(key, value)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given instance specification\n"
+ " " << is << "\n"
+ "that contains invalid field '" << *fi << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::ProcessGeneratorInstanceField(
+ std::string const& key, std::string const& value)
+{
+ if (key == "version") {
+ this->GeneratorInstanceVersion = value;
+ return true;
+ }
+ return false;
+}
+
bool cmGlobalVisualStudioVersionedGenerator::GetVSInstance(
std::string& dir) const
{
@@ -543,16 +691,16 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision()
const
{
switch (this->Version) {
- case cmGlobalVisualStudioGenerator::VS9:
- case cmGlobalVisualStudioGenerator::VS10:
- case cmGlobalVisualStudioGenerator::VS11:
- case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS9:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
return "";
- case cmGlobalVisualStudioGenerator::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
return "2.0";
- case cmGlobalVisualStudioGenerator::VS15:
- case cmGlobalVisualStudioGenerator::VS16:
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
return "3.0";
}
return "";
@@ -658,7 +806,7 @@ bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf)
// the target Windows version.
if (this->IsWin81SDKInstalled()) {
// VS 2019 does not default to 8.1 so specify it explicitly when needed.
- if (this->Version >= cmGlobalVisualStudioGenerator::VS16 &&
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 &&
!cmSystemTools::VersionCompareGreater(this->SystemVersion, "8.1")) {
this->SetWindowsTargetPlatformVersion("8.1", mf);
return true;
@@ -746,7 +894,7 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
// Ask Visual Studio Installer tool.
std::string vs;
if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
- if (this->Version >= cmGlobalVisualStudioGenerator::VS17) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {
msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe";
if (cmSystemTools::FileExists(msbuild)) {
return msbuild;
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
index 2aed65b..2e573ec 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.h
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -4,16 +4,18 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
#include <memory>
#include <string>
#include <cm/optional>
+#include "cmGlobalVisualStudio10Generator.h"
#include "cmGlobalVisualStudio14Generator.h"
+#include "cmGlobalVisualStudioGenerator.h"
#include "cmVSSetupHelper.h"
class cmGlobalGeneratorFactory;
+class cmMakefile;
class cmake;
/** \class cmGlobalVisualStudioVersionedGenerator */
@@ -65,6 +67,9 @@ protected:
std::string GetWindows10SDKMaxVersionDefault(cmMakefile*) const override;
+ virtual bool ProcessGeneratorInstanceField(std::string const& key,
+ std::string const& value);
+
std::string FindMSBuildCommand() override;
std::string FindDevEnvCommand() override;
@@ -76,5 +81,10 @@ private:
class Factory17;
friend class Factory17;
mutable cmVSSetupAPIHelper vsSetupAPIHelper;
+
+ bool ParseGeneratorInstance(std::string const& is, cmMakefile* mf);
+
+ std::string GeneratorInstance;
+ std::string GeneratorInstanceVersion;
cm::optional<std::string> LastGeneratorInstanceString;
};
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index 3e2d92d..fb2a8b6 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -65,12 +65,13 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ const std::string& config, int /*jobs*/, bool verbose,
+ const cmBuildOptions& buildOptions,
std::vector<std::string> const& makeOptions)
{
return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
- makeProgram, projectName, projectDir, targetNames, config, fast,
- cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+ makeProgram, projectName, projectDir, targetNames, config,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, buildOptions, makeOptions);
}
void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os,
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index da39d3f..eb93934 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "cmBuildOptions.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalUnixMakefileGenerator3.h"
@@ -57,7 +58,8 @@ protected:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index f34ef62..203addd 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -6,6 +6,7 @@
#include <cassert>
#include <cstdio>
#include <cstring>
+#include <functional>
#include <iomanip>
#include <sstream>
#include <unordered_set>
@@ -17,36 +18,42 @@
#include "cmsys/RegularExpression.hxx"
-#include "cmCMakePath.h"
#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGeneratorFactory.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalXCodeGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
+#include "cmPolicies.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmSourceGroup.h"
#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetDepend.h"
#include "cmXCode21Object.h"
#include "cmXCodeObject.h"
#include "cmXCodeScheme.h"
+#include "cmXMLWriter.h"
#include "cmake.h"
-struct cmLinkImplementation;
-
#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__)
# include <CoreFoundation/CoreFoundation.h>
# if !TARGET_OS_IPHONE
@@ -471,7 +478,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& /*projectDir*/,
std::vector<std::string> const& targetNames, const std::string& config,
- bool /*fast*/, int jobs, bool /*verbose*/,
+ int jobs, bool /*verbose*/, const cmBuildOptions& /*buildOptions*/,
std::vector<std::string> const& makeOptions)
{
GeneratedMakeCommand makeCommand;
@@ -601,15 +608,13 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
void cmGlobalXCodeGenerator::AddExtraTargets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
{
- const char* no_working_directory = nullptr;
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
-
// Add ALL_BUILD
- cmTarget* allbuild = root->AddUtilityCommand(
- "ALL_BUILD", true, no_working_directory, no_byproducts, no_depends,
- cmMakeSingleCommandLine({ "echo", "Build all projects" }),
- cmPolicies::NEW);
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCommandLines(
+ cmMakeSingleCommandLine({ "echo", "Build all projects" }));
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cmTarget* allbuild =
+ root->AddUtilityCommand("ALL_BUILD", true, std::move(cc));
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root));
@@ -635,10 +640,11 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
std::string file =
this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
- cmTarget* check = root->AddUtilityCommand(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_working_directory,
- no_byproducts, no_depends,
- cmMakeSingleCommandLine({ "make", "-f", file }), cmPolicies::NEW);
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCommandLines(cmMakeSingleCommandLine({ "make", "-f", file }));
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cmTarget* check = root->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET,
+ true, std::move(cc));
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(check, root));
}
@@ -664,11 +670,13 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
legacyDependHelperCommandLines.front().back() = // fill placeholder
this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCommandLines(legacyDependHelperCommandLines);
+ cc->SetComment("Depend check for xcode");
+ cc->SetWorkingDirectory(legacyDependHelperDir.c_str());
+ cc->SetCMP0116Status(cmPolicies::NEW);
gen->AddCustomCommandToTarget(
- target->GetName(), no_byproducts, no_depends,
- legacyDependHelperCommandLines, cmCustomCommandType::POST_BUILD,
- "Depend check for xcode", legacyDependHelperDir.c_str(),
- cmPolicies::NEW, true, false, "", "", false,
+ target->GetName(), cmCustomCommandType::POST_BUILD, std::move(cc),
cmObjectLibraryCommands::Accept);
}
@@ -833,8 +841,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateFlatClone(cmXCodeObject* orig)
return obj;
}
-std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target,
- const std::string& fullpath)
+static std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target,
+ const std::string& fullpath)
{
std::string key(target->GetName());
key += "-";
@@ -1716,15 +1724,16 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
std::string str_link_file =
cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
- bool stdPipesUTF8 = true;
cmCustomCommandLines cmd = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
str_file, str_so_file, str_link_file });
- cmCustomCommand command(
- std::vector<std::string>(), std::vector<std::string>(),
- std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(),
- "Creating symlinks", "", stdPipesUTF8);
+ cmCustomCommand command;
+ command.SetCommandLines(cmd);
+ command.SetComment("Creating symlinks");
+ command.SetWorkingDirectory("");
+ command.SetBacktrace(this->CurrentMakefile->GetBacktrace());
+ command.SetStdPipesUTF8(true);
postbuild.push_back(std::move(command));
}
@@ -2674,7 +2683,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (emitted.insert(frameworkDir).second) {
std::string incpath = this->XCodeEscapePath(frameworkDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(frameworkDir, configName,
+ gtgt->IsSystemIncludeDirectory(include, configName,
langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
@@ -3910,6 +3919,14 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
NoActionOnCopyByDefault);
}
+void cmGlobalXCodeGenerator::AddEmbeddedPlugIns(cmXCodeObject* target)
+{
+ static const auto dstSubfolderSpec = "13";
+
+ this->AddEmbeddedObjects(target, "Embed PlugIns", "XCODE_EMBED_PLUGINS",
+ dstSubfolderSpec, NoActionOnCopyByDefault);
+}
+
void cmGlobalXCodeGenerator::AddEmbeddedAppExtensions(cmXCodeObject* target)
{
static const auto dstSubfolderSpec = "13";
@@ -4298,6 +4315,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
for (auto t : targets) {
this->AddDependAndLinkInformation(t);
this->AddEmbeddedFrameworks(t);
+ this->AddEmbeddedPlugIns(t);
this->AddEmbeddedAppExtensions(t);
// Inherit project-wide values for any target-specific search paths.
this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS");
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 4d7ee90..ff6ffe8 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -11,10 +11,12 @@
#include <string>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include "cmGlobalGenerator.h"
#include "cmTransformDepfile.h"
+#include "cmValue.h"
#include "cmXCodeObject.h"
class cmCustomCommand;
@@ -78,7 +80,8 @@ public:
std::vector<GeneratedMakeCommand> GenerateBuildCommand(
const std::string& makeProgram, const std::string& projectName,
const std::string& projectDir, std::vector<std::string> const& targetNames,
- const std::string& config, bool fast, int jobs, bool verbose,
+ const std::string& config, int jobs, bool verbose,
+ const cmBuildOptions& buildOptions = cmBuildOptions(),
std::vector<std::string> const& makeOptions =
std::vector<std::string>()) override;
@@ -216,6 +219,7 @@ private:
const std::string& dstSubfolderSpec,
int actionsOnByDefault);
void AddEmbeddedFrameworks(cmXCodeObject* target);
+ void AddEmbeddedPlugIns(cmXCodeObject* target);
void AddEmbeddedAppExtensions(cmXCodeObject* target);
void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
cmXCodeObject* buildSettings,
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index b53319f..c09aa46 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -2,15 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIDEOptions.h"
+#include <algorithm>
+#include <cstring>
#include <iterator>
+#include <utility>
#include <cmext/algorithm>
-#include <string.h>
-
#include "cmsys/String.h"
-#include "cmAlgorithms.h"
#include "cmIDEFlagTable.h"
#include "cmStringAlgorithms.h"
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 92e3bb5..8ce7ed1 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -6,11 +6,13 @@
#include <cassert>
#include <cstddef>
#include <iterator>
+#include <map>
#include <set>
#include <sstream>
#include <utility>
#include <cm/memory>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmsys/Glob.hxx"
@@ -18,11 +20,13 @@
#include "cmArgumentParser.h"
#include "cmExecutionStatus.h"
#include "cmExportSet.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCommandArguments.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmInstallGetRuntimeDependenciesGenerator.h"
@@ -89,6 +93,9 @@ public:
bool MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles);
+ bool MakeFilesFullPath(const char* modeName, const std::string& basePath,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles);
bool CheckCMP0006(bool& failure) const;
std::string GetDestination(const cmInstallCommandArguments* args,
@@ -177,6 +184,19 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
args.GetDestination());
}
+std::unique_ptr<cmInstallFileSetGenerator> CreateInstallFileSetGenerator(
+ Helper& helper, cmTarget& target, cmFileSet* fileSet,
+ const std::string& destination, const cmInstallCommandArguments& args)
+{
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile);
+ return cm::make_unique<cmInstallFileSetGenerator>(
+ target.GetName(), fileSet, destination, args.GetPermissions(),
+ args.GetConfigurations(), args.GetComponent(), message,
+ args.GetExcludeFromAll(), args.GetOptional(),
+ helper.Makefile->GetBacktrace());
+}
+
void AddInstallRuntimeDependenciesGenerator(
Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
const cmInstallCommandArguments& runtimeArgs,
@@ -390,6 +410,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::vector<std::string> PrivateHeader;
std::vector<std::string> PublicHeader;
std::vector<std::string> Resource;
+ std::vector<std::vector<std::string>> FileSets;
};
static auto const argHelper =
@@ -403,7 +424,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
.Bind("INCLUDES"_s, &ArgVectors::Includes)
.Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
.Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
- .Bind("RESOURCE"_s, &ArgVectors::Resource);
+ .Bind("RESOURCE"_s, &ArgVectors::Resource)
+ .Bind("FILE_SET"_s, &ArgVectors::FileSets);
std::vector<std::string> genericArgVector;
ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
@@ -442,6 +464,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
cmInstallCommandIncludesArgument includesArgs;
+ std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
+ argVectors.FileSets.size(), { helper.DefaultComponentName });
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -455,6 +479,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
resourceArgs.Parse(argVectors.Resource, &unknownArgs);
includesArgs.Parse(&argVectors.Includes, &unknownArgs);
+ for (std::size_t i = 0; i < argVectors.FileSets.size(); i++) {
+ // We have to create a separate object for the parsing because
+ // cmArgumentParser<void>::Bind() binds to a specific address, but the
+ // objects in the vector can move around. So we parse in an object with a
+ // fixed address and then copy the data into the vector.
+ cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName);
+ fileSetArg.Parse(argVectors.FileSets[i], &unknownArgs);
+ fileSetArgs[i] = std::move(fileSetArg);
+ }
if (!unknownArgs.empty()) {
// Unknown argument.
@@ -473,6 +506,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
privateHeaderArgs.SetGenericArguments(&genericArgs);
publicHeaderArgs.SetGenericArguments(&genericArgs);
resourceArgs.SetGenericArguments(&genericArgs);
+ for (auto& fileSetArg : fileSetArgs) {
+ fileSetArg.SetGenericArguments(&genericArgs);
+ }
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
@@ -483,6 +519,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
success = success && privateHeaderArgs.Finalize();
success = success && publicHeaderArgs.Finalize();
success = success && resourceArgs.Finalize();
+ for (auto& fileSetArg : fileSetArgs) {
+ success = success && fileSetArg.Finalize();
+ }
if (!success) {
return false;
@@ -493,7 +532,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
- publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
+ publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetNamelinkOnly(); })) {
status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
@@ -502,7 +544,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
- publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
+ publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetNamelinkSkip(); })) {
status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
@@ -515,7 +560,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bundleArgs.HasNamelinkComponent() ||
privateHeaderArgs.HasNamelinkComponent() ||
publicHeaderArgs.HasNamelinkComponent() ||
- resourceArgs.HasNamelinkComponent()) {
+ resourceArgs.HasNamelinkComponent() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.HasNamelinkComponent(); })) {
status.SetError(
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
"The NAMELINK_COMPONENT option may be specified only following "
@@ -531,12 +579,21 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
!libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
!objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
!bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
- !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
+ !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() ||
+ std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return !fileSetArg.GetType().empty(); })) {
status.SetError(
"TARGETS given TYPE option. The TYPE option may only be specified in "
" install(FILES) and install(DIRECTORIES).");
return false;
}
+ if (std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
+ [](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetFileSet().empty(); })) {
+ status.SetError("TARGETS given FILE_SET option without file set name.");
+ return false;
+ }
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
if (withRuntimeDependencies) {
@@ -647,6 +704,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bool installsPrivateHeader = false;
bool installsPublicHeader = false;
bool installsResource = false;
+ std::vector<bool> installsFileSet(fileSetArgs.size(), false);
// Generate install script code to install the given targets.
for (cmTarget* ti : targets) {
@@ -662,6 +720,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::unique_ptr<cmInstallFilesGenerator> privateHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
+ std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators;
// Avoid selecting default destinations for PUBLIC_HEADER and
// PRIVATE_HEADER if any artifacts are specified.
@@ -670,9 +729,24 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// Track whether this is a namelink-only rule.
bool namelinkOnly = false;
- auto addTargetExport = [&]() {
+ auto addTargetExport = [&]() -> bool {
// Add this install rule to an export if one was specified.
if (!exports.empty()) {
+ auto interfaceFileSets = target.GetAllInterfaceFileSets();
+ if (std::any_of(
+ interfaceFileSets.begin(), interfaceFileSets.end(),
+ [=](const std::string& name) -> bool {
+ return !std::any_of(
+ fileSetArgs.begin(), fileSetArgs.end(),
+ [=](const cmInstallCommandFileSetArguments& fileSetArg)
+ -> bool { return fileSetArg.GetFileSet() == name; });
+ })) {
+ status.SetError(cmStrCat(
+ "TARGETS target ", target.GetName(),
+ " is exported but not all of its file sets are installed"));
+ return false;
+ }
+
auto te = cm::make_unique<cmTargetExport>();
te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator.get();
@@ -682,6 +756,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
te->LibraryGenerator = libraryGenerator.get();
te->RuntimeGenerator = runtimeGenerator.get();
te->ObjectsGenerator = objectGenerator.get();
+ for (auto const& gen : fileSetGenerators) {
+ te->FileSetGenerators[gen->GetFileSet()] = gen.get();
+ }
target.AddInstallIncludeDirectories(
*te, cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
@@ -689,6 +766,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
->GetExportSets()[exports]
.AddTargetExport(std::move(te));
}
+ return true;
};
switch (target.GetType()) {
@@ -700,7 +778,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip all libraries on Windows.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -736,7 +816,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -785,7 +867,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// When in namelink only mode skip frameworks.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
namelinkOnly = true;
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
continue;
}
@@ -942,9 +1026,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.GetIncludeDestination(&privateHeaderArgs));
} else {
std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
+ e << "Target " << target.GetName() << " has "
<< "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
- cmSystemTools::Message(e.str(), "Warning");
+ helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
}
@@ -964,9 +1048,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.GetIncludeDestination(&publicHeaderArgs));
} else {
std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
+ e << "Target " << target.GetName() << " has "
<< "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
- cmSystemTools::Message(e.str(), "Warning");
+ helper.Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
}
@@ -983,16 +1067,48 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
resourceGenerator = CreateInstallFilesGenerator(
helper.Makefile, absFiles, resourceArgs, false);
} else if (!target.IsAppBundleOnApple()) {
- cmSystemTools::Message(
- cmStrCat("INSTALL TARGETS - target ", target.GetName(),
- " has RESOURCE files but no RESOURCE DESTINATION."),
- "Warning");
+ helper.Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("Target ", target.GetName(),
+ " has RESOURCE files but no RESOURCE DESTINATION."));
+ }
+ }
+ }
+
+ if (!namelinkOnly) {
+ for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
+ if (auto* fileSet = target.GetFileSet(fileSetArgs[i].GetFileSet())) {
+ auto interfaceFileSetEntries = cmExpandedList(target.GetSafeProperty(
+ cmTarget::GetInterfaceFileSetsPropertyName(fileSet->GetType())));
+ if (std::find(interfaceFileSetEntries.begin(),
+ interfaceFileSetEntries.end(),
+ fileSetArgs[i].GetFileSet()) !=
+ interfaceFileSetEntries.end()) {
+ std::string destination;
+ if (fileSet->GetType() == "HEADERS"_s) {
+ destination = helper.GetIncludeDestination(&fileSetArgs[i]);
+ } else {
+ destination = fileSetArgs[i].GetDestination();
+ if (destination.empty()) {
+ status.SetError(cmStrCat(
+ "TARGETS given no FILE_SET DESTINATION for target \"",
+ target.GetName(), "\" file set \"", fileSet->GetName(),
+ "\"."));
+ return false;
+ }
+ }
+ fileSetGenerators.push_back(CreateInstallFileSetGenerator(
+ helper, target, fileSet, destination, fileSetArgs[i]));
+ installsFileSet[i] = true;
+ }
}
}
}
// Add this install rule to an export if one was specified.
- addTargetExport();
+ if (!addTargetExport()) {
+ return false;
+ }
// Keep track of whether we're installing anything in each category
installsArchive = installsArchive || archiveGenerator;
@@ -1016,6 +1132,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->AddInstallGenerator(std::move(privateHeaderGenerator));
helper.Makefile->AddInstallGenerator(std::move(publicHeaderGenerator));
helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
+ for (auto& gen : fileSetGenerators) {
+ helper.Makefile->AddInstallGenerator(std::move(gen));
+ }
}
if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
@@ -1067,6 +1186,12 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
resourceArgs.GetComponent());
}
+ for (std::size_t i = 0; i < fileSetArgs.size(); i++) {
+ if (installsFileSet[i]) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ fileSetArgs[i].GetComponent());
+ }
+ }
return true;
}
@@ -2063,12 +2188,20 @@ bool Helper::MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles)
{
+ return this->MakeFilesFullPath(
+ modeName, this->Makefile->GetCurrentSourceDirectory(), relFiles, absFiles);
+}
+
+bool Helper::MakeFilesFullPath(const char* modeName,
+ const std::string& basePath,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles)
+{
for (std::string const& relFile : relFiles) {
std::string file = relFile;
std::string::size_type gpos = cmGeneratorExpression::Find(file);
if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
- file =
- cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile);
+ file = cmStrCat(basePath, '/', relFile);
}
// Make sure the file is not a directory.
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index cc3df2a..7309316 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -152,6 +152,11 @@ const std::string& cmInstallCommandArguments::GetType() const
return this->Type;
}
+const std::string& cmInstallCommandArguments::GetDefaultComponent() const
+{
+ return this->DefaultComponentName;
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
@@ -220,3 +225,17 @@ void cmInstallCommandIncludesArgument::Parse(
this->IncludeDirs.push_back(std::move(dir));
}
}
+
+cmInstallCommandFileSetArguments::cmInstallCommandFileSetArguments(
+ std::string defaultComponent)
+ : cmInstallCommandArguments(std::move(defaultComponent))
+{
+ this->Bind("FILE_SET"_s, this->FileSet);
+}
+
+void cmInstallCommandFileSetArguments::Parse(
+ std::vector<std::string> args, std::vector<std::string>* unconsumedArgs)
+{
+ args.insert(args.begin(), "FILE_SET");
+ this->cmInstallCommandArguments::Parse(args, unconsumedArgs);
+}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index f318a1a..79bd945 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -34,6 +34,8 @@ public:
bool HasNamelinkComponent() const;
const std::string& GetType() const;
+ const std::string& GetDefaultComponent() const;
+
static bool CheckPermissions(const std::string& onePerm, std::string& perm);
private:
@@ -71,3 +73,17 @@ public:
private:
std::vector<std::string> IncludeDirs;
};
+
+class cmInstallCommandFileSetArguments : public cmInstallCommandArguments
+{
+public:
+ cmInstallCommandFileSetArguments(std::string defaultComponent);
+
+ void Parse(std::vector<std::string> args,
+ std::vector<std::string>* unconsumedArgs);
+
+ const std::string& GetFileSet() const { return this->FileSet; }
+
+private:
+ std::string FileSet;
+};
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index d932fd9..820f24a 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -85,7 +85,9 @@ void cmInstallExportGenerator::ComputeTempDir()
}
if (useMD5) {
// Replace the destination path with a hash to keep it short.
+#ifndef CMAKE_BOOTSTRAP
this->TempDir += cmSystemTools::ComputeStringMD5(this->Destination);
+#endif
} else {
std::string dest = this->Destination;
// Avoid unix full paths.
diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx
new file mode 100644
index 0000000..7121ea3
--- /dev/null
+++ b/Source/cmInstallFileSetGenerator.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 "cmInstallFileSetGenerator.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmFileSet.h"
+#include "cmGeneratorExpression.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallType.h"
+#include "cmLocalGenerator.h"
+#include "cmStringAlgorithms.h"
+
+cmInstallFileSetGenerator::cmInstallFileSetGenerator(
+ std::string targetName, cmFileSet* fileSet, std::string const& dest,
+ std::string file_permissions, std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message, bool exclude_from_all,
+ bool optional, cmListFileBacktrace backtrace)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all, false, std::move(backtrace))
+ , TargetName(std::move(targetName))
+ , FileSet(fileSet)
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+cmInstallFileSetGenerator::~cmInstallFileSetGenerator() = default;
+
+bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+
+ // Lookup this target in the current directory.
+ this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallFileSetGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
+}
+
+void cmInstallFileSetGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ for (auto const& dirEntry : this->CalculateFilesPerDir(config)) {
+ std::string destSub;
+ if (!dirEntry.first.empty()) {
+ destSub = cmStrCat('/', dirEntry.first);
+ }
+ this->AddInstallRule(os, cmStrCat(this->GetDestination(config), destSub),
+ cmInstallType_FILES, dirEntry.second,
+ this->GetOptional(), this->FilePermissions.c_str(),
+ nullptr, nullptr, nullptr, indent);
+ }
+}
+
+std::map<std::string, std::vector<std::string>>
+cmInstallFileSetGenerator::CalculateFilesPerDir(
+ const std::string& config) const
+{
+ std::map<std::string, std::vector<std::string>> result;
+
+ auto dirCges = this->FileSet->CompileDirectoryEntries();
+ auto dirs = this->FileSet->EvaluateDirectoryEntries(
+ dirCges, this->LocalGenerator, config, this->Target);
+
+ auto fileCges = this->FileSet->CompileFileEntries();
+ for (auto const& fileCge : fileCges) {
+ this->FileSet->EvaluateFileEntry(
+ dirs, result, fileCge, this->LocalGenerator, config, this->Target);
+ }
+
+ return result;
+}
diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h
new file mode 100644
index 0000000..8d067d9
--- /dev/null
+++ b/Source/cmInstallFileSetGenerator.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. */
+#pragma once
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmFileSet;
+class cmLocalGenerator;
+
+class cmInstallFileSetGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallFileSetGenerator(std::string targetName, cmFileSet* fileSet,
+ std::string const& dest,
+ std::string file_permissions,
+ std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message,
+ bool exclude_from_all, bool optional,
+ cmListFileBacktrace backtrace);
+ ~cmInstallFileSetGenerator() override;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ std::string GetDestination(std::string const& config) const;
+ std::string GetDestination() const { return this->Destination; }
+ bool GetOptional() const { return this->Optional; }
+ cmFileSet* GetFileSet() const { return this->FileSet; }
+ cmGeneratorTarget* GetTarget() const { return this->Target; }
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+private:
+ std::string TargetName;
+ cmLocalGenerator* LocalGenerator;
+ cmFileSet* const FileSet;
+ std::string const FilePermissions;
+ bool const Optional;
+ cmGeneratorTarget* Target;
+
+ std::map<std::string, std::vector<std::string>> CalculateFilesPerDir(
+ const std::string& config) const;
+};
diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx
index 62e7ef4..2dc40ff 100644
--- a/Source/cmLinkItem.cxx
+++ b/Source/cmLinkItem.cxx
@@ -68,8 +68,8 @@ cmLinkImplItem::cmLinkImplItem()
{
}
-cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool fromGenex)
+cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool checkCMP0027)
: cmLinkItem(std::move(item))
- , FromGenex(fromGenex)
+ , CheckCMP0027(checkCMP0027)
{
}
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 0863edd..262728b 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -40,8 +40,8 @@ class cmLinkImplItem : public cmLinkItem
{
public:
cmLinkImplItem();
- cmLinkImplItem(cmLinkItem item, bool fromGenex);
- bool FromGenex = false;
+ cmLinkImplItem(cmLinkItem item, bool checkCMP0027);
+ bool CheckCMP0027 = false;
};
/** The link implementation specifies the direct library
@@ -70,6 +70,12 @@ struct cmLinkInterfaceLibraries
// Object files listed in the interface.
std::vector<cmLinkItem> Objects;
+ // Items to be included as if directly linked by the head target.
+ std::vector<cmLinkItem> HeadInclude;
+
+ // Items to be excluded from direct linking by the head target.
+ std::vector<cmLinkItem> HeadExclude;
+
// Whether the list depends on a genex referencing the head target.
bool HadHeadSensitiveCondition = false;
diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx
index 7ad8690..d87d183 100644
--- a/Source/cmLinkItemGraphVisitor.cxx
+++ b/Source/cmLinkItemGraphVisitor.cxx
@@ -107,8 +107,8 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
}
}
- const auto* interfaceLibraries =
- target.GetLinkInterfaceLibraries(config, &target, true);
+ const auto* interfaceLibraries = target.GetLinkInterfaceLibraries(
+ config, &target, cmGeneratorTarget::LinkInterfaceFor::Usage);
if (interfaceLibraries != nullptr) {
for (auto const& lib : interfaceLibraries->Libraries) {
auto const& name = lib.AsStr();
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 7d42fc8..56345df 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -155,7 +155,7 @@ bool HandleLengthCommand(std::vector<std::string> const& args,
GetList(varArgsExpanded, listName, status.GetMakefile());
size_t length = varArgsExpanded.size();
char buffer[1024];
- sprintf(buffer, "%d", static_cast<int>(length));
+ snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(length));
status.GetMakefile().AddDefinition(variableName, buffer);
return true;
@@ -678,6 +678,14 @@ public:
this->Start = this->NormalizeIndex(this->Start, count);
this->Stop = this->NormalizeIndex(this->Stop, count);
+ // Does stepping move us further from the end?
+ if (this->Start > this->Stop) {
+ throw transform_error(
+ cmStrCat("sub-command TRANSFORM, selector FOR "
+ "expects <start> to be no greater than <stop> (",
+ this->Start, " > ", this->Stop, ")"));
+ }
+
// compute indexes
auto size = (this->Stop - this->Start + 1) / this->Step;
if ((this->Stop - this->Start + 1) % this->Step != 0) {
@@ -1026,9 +1034,10 @@ bool HandleTransformCommand(std::vector<std::string> const& args,
}
}
- if (step < 0) {
+ if (step <= 0) {
status.SetError("sub-command TRANSFORM, selector FOR expects "
- "non negative numeric value for <step>.");
+ "positive numeric value for <step>.");
+ return false;
}
command.Selector =
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 2e444f2..3da266d 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -14,7 +14,6 @@
#include "cmListFileLexer.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
-#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -370,68 +369,68 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const
if (name == "if") {
stack.push_back({
NestingStateEnum::If,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
});
} else if (name == "elseif") {
if (!TopIs(stack, NestingStateEnum::If)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.back() = {
NestingStateEnum::If,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
};
} else if (name == "else") {
if (!TopIs(stack, NestingStateEnum::If)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.back() = {
NestingStateEnum::Else,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
};
} else if (name == "endif") {
if (!TopIs(stack, NestingStateEnum::If) &&
!TopIs(stack, NestingStateEnum::Else)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
} else if (name == "while") {
stack.push_back({
NestingStateEnum::While,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
});
} else if (name == "endwhile") {
if (!TopIs(stack, NestingStateEnum::While)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
} else if (name == "foreach") {
stack.push_back({
NestingStateEnum::Foreach,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
});
} else if (name == "endforeach") {
if (!TopIs(stack, NestingStateEnum::Foreach)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
} else if (name == "function") {
stack.push_back({
NestingStateEnum::Function,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
});
} else if (name == "endfunction") {
if (!TopIs(stack, NestingStateEnum::Function)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
} else if (name == "macro") {
stack.push_back({
NestingStateEnum::Macro,
- cmListFileContext::FromCommandContext(func, this->FileName),
+ cmListFileContext::FromListFileFunction(func, this->FileName),
});
} else if (name == "endmacro") {
if (!TopIs(stack, NestingStateEnum::Macro)) {
- return cmListFileContext::FromCommandContext(func, this->FileName);
+ return cmListFileContext::FromListFileFunction(func, this->FileName);
}
stack.pop_back();
}
@@ -444,45 +443,19 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const
return cm::nullopt;
}
-// We hold either the bottom scope of a directory or a call/file context.
-// Discriminate these cases via the parent pointer.
+// We hold a call/file context.
struct cmListFileBacktrace::Entry
{
- Entry(cmStateSnapshot bottom)
- : Bottom(bottom)
- {
- }
-
Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc)
: Context(std::move(lfc))
, Parent(std::move(parent))
{
}
- ~Entry()
- {
- if (this->Parent) {
- this->Context.~cmListFileContext();
- } else {
- this->Bottom.~cmStateSnapshot();
- }
- }
-
- bool IsBottom() const { return !this->Parent; }
-
- union
- {
- cmStateSnapshot Bottom;
- cmListFileContext Context;
- };
+ cmListFileContext Context;
std::shared_ptr<Entry const> Parent;
};
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
- : TopEntry(std::make_shared<Entry const>(snapshot.GetCallStackBottom()))
-{
-}
-
/* NOLINTNEXTLINE(performance-unnecessary-value-param) */
cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc)
@@ -495,18 +468,6 @@ cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top)
{
}
-cmStateSnapshot cmListFileBacktrace::GetBottom() const
-{
- cmStateSnapshot bottom;
- if (Entry const* cur = this->TopEntry.get()) {
- while (Entry const* parent = cur->Parent.get()) {
- cur = parent;
- }
- bottom = cur->Bottom;
- }
- return bottom;
-}
-
cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
{
// We are entering a file-level scope but have not yet reached
@@ -521,86 +482,24 @@ cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
cmListFileBacktrace cmListFileBacktrace::Push(
cmListFileContext const& lfc) const
{
- assert(this->TopEntry);
- assert(!this->TopEntry->IsBottom() || this->TopEntry->Bottom.IsValid());
return cmListFileBacktrace(this->TopEntry, lfc);
}
cmListFileBacktrace cmListFileBacktrace::Pop() const
{
assert(this->TopEntry);
- assert(!this->TopEntry->IsBottom());
return cmListFileBacktrace(this->TopEntry->Parent);
}
cmListFileContext const& cmListFileBacktrace::Top() const
{
assert(this->TopEntry);
- assert(!this->TopEntry->IsBottom());
return this->TopEntry->Context;
}
-void cmListFileBacktrace::PrintTitle(std::ostream& out) const
-{
- // The title exists only if we have a call on top of the bottom.
- if (!this->TopEntry || this->TopEntry->IsBottom()) {
- return;
- }
- cmListFileContext lfc = this->TopEntry->Context;
- cmStateSnapshot bottom = this->GetBottom();
- if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
- lfc.FilePath = cmSystemTools::RelativeIfUnder(
- bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
- }
- out << (lfc.Line ? " at " : " in ") << lfc;
-}
-
-void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
-{
- // The call stack exists only if we have at least two calls on top
- // of the bottom.
- if (!this->TopEntry || this->TopEntry->IsBottom() ||
- this->TopEntry->Parent->IsBottom()) {
- return;
- }
-
- bool first = true;
- cmStateSnapshot bottom = this->GetBottom();
- for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom();
- cur = cur->Parent.get()) {
- if (cur->Context.Name.empty() &&
- cur->Context.Line != cmListFileContext::DeferPlaceholderLine) {
- // Skip this whole-file scope. When we get here we already will
- // have printed a more-specific context within the file.
- continue;
- }
- if (first) {
- first = false;
- out << "Call Stack (most recent call first):\n";
- }
- cmListFileContext lfc = cur->Context;
- if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
- lfc.FilePath = cmSystemTools::RelativeIfUnder(
- bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
- }
- out << " " << lfc << "\n";
- }
-}
-
-size_t cmListFileBacktrace::Depth() const
-{
- size_t depth = 0;
- if (Entry const* cur = this->TopEntry.get()) {
- for (; !cur->IsBottom(); cur = cur->Parent.get()) {
- ++depth;
- }
- }
- return depth;
-}
-
bool cmListFileBacktrace::Empty() const
{
- return !this->TopEntry || this->TopEntry->IsBottom();
+ return !this->TopEntry;
}
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 98cb4a7..5d45027 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -4,7 +4,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <cstddef>
#include <iosfwd>
#include <memory>
#include <string>
@@ -13,7 +12,6 @@
#include <cm/optional>
-#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
/** \class cmListFileCache
@@ -25,28 +23,6 @@
class cmMessenger;
-struct cmCommandContext
-{
- struct cmCommandName
- {
- std::string Original;
- std::string Lower;
- cmCommandName() = default;
- cmCommandName(std::string name)
- : Original(std::move(name))
- , Lower(cmSystemTools::LowerCase(this->Original))
- {
- }
- } Name;
- long Line = 0;
- cmCommandContext() = default;
- cmCommandContext(std::string name, long line)
- : Name(std::move(name))
- , Line(line)
- {
- }
-};
-
struct cmListFileArgument
{
enum Delimiter
@@ -72,49 +48,6 @@ struct cmListFileArgument
long Line = 0;
};
-class cmListFileContext
-{
-public:
- std::string Name;
- std::string FilePath;
- long Line = 0;
- static long const DeferPlaceholderLine = -1;
- cm::optional<std::string> DeferId;
-
- cmListFileContext() = default;
- cmListFileContext(std::string name, std::string filePath, long line)
- : Name(std::move(name))
- , FilePath(std::move(filePath))
- , Line(line)
- {
- }
-
-#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
- cmListFileContext(const cmListFileContext& /*other*/) = default;
- cmListFileContext(cmListFileContext&& /*other*/) = default;
-
- cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
- cmListFileContext& operator=(cmListFileContext&& /*other*/) = delete;
-#endif
-
- static cmListFileContext FromCommandContext(
- cmCommandContext const& lfcc, std::string const& fileName,
- cm::optional<std::string> deferId = {})
- {
- cmListFileContext lfc;
- lfc.FilePath = fileName;
- lfc.Line = lfcc.Line;
- lfc.Name = lfcc.Name.Original;
- lfc.DeferId = std::move(deferId);
- 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);
-
class cmListFileFunction
{
public:
@@ -127,12 +60,12 @@ public:
std::string const& OriginalName() const noexcept
{
- return this->Impl->Name.Original;
+ return this->Impl->OriginalName;
}
std::string const& LowerCaseName() const noexcept
{
- return this->Impl->Name.Lower;
+ return this->Impl->LowerCaseName;
}
long Line() const noexcept { return this->Impl->Line; }
@@ -142,45 +75,86 @@ public:
return this->Impl->Arguments;
}
- operator cmCommandContext const&() const noexcept { return *this->Impl; }
-
private:
- struct Implementation : public cmCommandContext
+ struct Implementation
{
Implementation(std::string name, long line,
std::vector<cmListFileArgument> args)
- : cmCommandContext{ std::move(name), line }
+ : OriginalName{ std::move(name) }
+ , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) }
+ , Line{ line }
, Arguments{ std::move(args) }
{
}
+
+ std::string OriginalName;
+ std::string LowerCaseName;
+ long Line = 0;
std::vector<cmListFileArgument> Arguments;
};
std::shared_ptr<Implementation const> Impl;
};
+class cmListFileContext
+{
+public:
+ std::string Name;
+ std::string FilePath;
+ long Line = 0;
+ static long const DeferPlaceholderLine = -1;
+ cm::optional<std::string> DeferId;
+
+ cmListFileContext() = default;
+ cmListFileContext(cmListFileContext&& /*other*/) = default;
+ cmListFileContext(const cmListFileContext& /*other*/) = default;
+ cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ cmListFileContext& operator=(cmListFileContext&& /*other*/) = default;
+#else
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't.
+ cmListFileContext& operator=(cmListFileContext&& /*other*/) = delete;
+#endif
+
+ cmListFileContext(std::string name, std::string filePath, long line)
+ : Name(std::move(name))
+ , FilePath(std::move(filePath))
+ , Line(line)
+ {
+ }
+
+ static cmListFileContext FromListFileFunction(
+ cmListFileFunction const& lff, std::string const& fileName,
+ cm::optional<std::string> deferId = {})
+ {
+ cmListFileContext lfc;
+ lfc.FilePath = fileName;
+ lfc.Line = lff.Line();
+ lfc.Name = lff.OriginalName();
+ lfc.DeferId = std::move(deferId);
+ 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);
+
// 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.
+ // Default-constructed backtrace is empty.
cmListFileBacktrace() = default;
- // Construct an empty backtrace whose bottom sits in the directory
- // indicated by the given valid snapshot.
- cmListFileBacktrace(cmStateSnapshot const& snapshot);
-
- cmStateSnapshot GetBottom() const;
-
// Get a backtrace with the given file scope added to the top.
- // May not be called until after construction with a valid snapshot.
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.
@@ -191,15 +165,6 @@ public:
// This may be called only if Empty() would return false.
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;
-
- // Get the number of 'frames' in this backtrace
- size_t Depth() const;
-
// Return true if this backtrace is empty.
bool Empty() const;
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 2456db9..2080b40 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -44,6 +44,7 @@ namespace {
const char* LastName = nullptr;
+extern "C" void TrapsForSignals(int sig);
extern "C" void TrapsForSignals(int sig)
{
fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index fc5e6e5..2adb232 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -37,6 +37,7 @@
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
@@ -834,16 +835,14 @@ cmValue cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
}
std::string cmLocalGenerator::ConvertToIncludeReference(
- std::string const& path, IncludePathStyle pathStyle, OutputFormat format)
+ std::string const& path, OutputFormat format)
{
- static_cast<void>(pathStyle);
return this->ConvertToOutputForExisting(path, format);
}
std::string cmLocalGenerator::GetIncludeFlags(
std::vector<std::string> const& includeDirs, cmGeneratorTarget* target,
- std::string const& lang, std::string const& config, bool forResponseFile,
- IncludePathStyle pathStyle)
+ std::string const& lang, std::string const& config, bool forResponseFile)
{
if (lang.empty()) {
return "";
@@ -922,8 +921,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
flagUsed = true;
}
- std::string includePath =
- this->ConvertToIncludeReference(i, pathStyle, shellFormat);
+ std::string includePath = this->ConvertToIncludeReference(i, shellFormat);
if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
@@ -1056,14 +1054,8 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
}
cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
- const std::string& target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir,
- cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle, bool uses_terminal,
- const std::string& depfile, const std::string& job_pool,
- bool command_expand_lists, cmObjectLibraryCommands objLibCommands,
- bool stdPipesUTF8)
+ const std::string& target, cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc, cmObjectLibraryCommands objLibCommands)
{
cmTarget* t = this->Makefile->GetCustomCommandTarget(
target, objLibCommands, this->DirectoryBacktrace);
@@ -1071,74 +1063,43 @@ cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
return nullptr;
}
- detail::AddCustomCommandToTarget(
- *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts,
- depends, commandLines, type, comment, workingDir, escapeOldStyle,
- uses_terminal, depfile, job_pool, command_expand_lists, stdPipesUTF8,
- cmp0116);
+ cc->SetBacktrace(this->DirectoryBacktrace);
- return t;
-}
+ detail::AddCustomCommandToTarget(*this, cmCommandOrigin::Generator, t, type,
+ std::move(cc));
-cmSourceFile* cmLocalGenerator::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,
- cmPolicies::PolicyStatus cmp0116, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
-{
- std::vector<std::string> no_byproducts;
- cmImplicitDependsList no_implicit_depends;
- return this->AddCustomCommandToOutput(
- { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
- commandLines, comment, workingDir, cmp0116, replace, escapeOldStyle,
- uses_terminal, command_expand_lists, depfile, job_pool, stdPipesUTF8);
+ return t;
}
cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, cmPolicies::PolicyStatus cmp0116, bool replace,
- bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
- const std::string& depfile, const std::string& job_pool, bool stdPipesUTF8)
+ std::unique_ptr<cmCustomCommand> cc, bool replace)
{
// Make sure there is at least one output.
- if (outputs.empty()) {
+ if (cc->GetOutputs().empty()) {
cmSystemTools::Error("Attempt to add a custom rule with no output!");
return nullptr;
}
- return detail::AddCustomCommandToOutput(
- *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs,
- byproducts, depends, main_dependency, implicit_depends, commandLines,
- comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool, stdPipesUTF8, cmp0116);
+ cc->SetBacktrace(this->DirectoryBacktrace);
+ return detail::AddCustomCommandToOutput(*this, cmCommandOrigin::Generator,
+ std::move(cc), replace);
}
cmTarget* cmLocalGenerator::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll, const char* workingDir,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
- bool escapeOldStyle, const char* comment, bool uses_terminal,
- bool command_expand_lists, const std::string& job_pool, bool stdPipesUTF8)
+ const std::string& utilityName, bool excludeFromAll,
+ std::unique_ptr<cmCustomCommand> cc)
{
cmTarget* target =
this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll);
target->SetIsGeneratorProvided(true);
- if (commandLines.empty() && depends.empty()) {
+ if (cc->GetCommandLines().empty() && cc->GetDepends().empty()) {
return target;
}
- detail::AddUtilityCommand(
- *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target,
- workingDir, byproducts, depends, commandLines, escapeOldStyle, comment,
- uses_terminal, command_expand_lists, job_pool, stdPipesUTF8, cmp0116);
+ cc->SetBacktrace(this->DirectoryBacktrace);
+ detail::AddUtilityCommand(*this, cmCommandOrigin::Generator, target,
+ std::move(cc));
return target;
}
@@ -1410,25 +1371,23 @@ std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags(
}
void cmLocalGenerator::GetDeviceLinkFlags(
- cmLinkLineComputer* linkLineComputer, const std::string& config,
+ cmLinkLineComputer& linkLineComputer, const std::string& config,
std::string& linkLibs, std::string& linkFlags, std::string& frameworkPath,
std::string& linkPath, cmGeneratorTarget* target)
{
cmGeneratorTarget::DeviceLinkSetter setter(*target);
cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
- const std::string linkLanguage =
- linkLineComputer->GetLinkerLanguage(target, config);
if (pcli) {
// Compute the required device link libraries when
// resolving gpu lang device symbols
- this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath,
+ this->OutputLinkLibraries(pcli, &linkLineComputer, linkLibs, frameworkPath,
linkPath);
}
std::vector<std::string> linkOpts;
- target->GetLinkOptions(linkOpts, config, linkLanguage);
+ target->GetLinkOptions(linkOpts, config, "CUDA");
// LINK_OPTIONS are escaped.
this->AppendCompileOptions(linkFlags, linkOpts);
}
@@ -2656,10 +2615,15 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
true);
} else if (reuseTarget->GetType() ==
cmStateEnums::OBJECT_LIBRARY) {
+ // FIXME: This can propagate more than one level, unlike
+ // the rest of the object files in an object library.
+ // Find another way to do this.
target->Target->AppendProperty(
"INTERFACE_LINK_LIBRARIES",
cmStrCat("$<$<CONFIG:", config,
">:$<LINK_ONLY:", pchSourceObj, ">>"));
+ // We updated the link interface, so ensure it is recomputed.
+ target->ClearLinkInterfaceCache();
}
}
} else {
@@ -2751,8 +2715,6 @@ void cmLocalGenerator::CopyPchCompilePdb(
file << "endforeach()\n";
}
- bool stdPipesUTF8 = true;
-
auto configGenex = [&](cm::string_view expr) -> std::string {
if (this->GetGlobalGenerator()->IsMultiConfig()) {
return cmStrCat("$<$<CONFIG:", config, ">:", expr, ">");
@@ -2765,29 +2727,26 @@ void cmLocalGenerator::CopyPchCompilePdb(
configGenex(cmStrCat("-DPDB_PREFIX=", pdb_prefix)), configGenex("-P"),
configGenex(copy_script) });
- const std::string no_main_dependency;
- const std::vector<std::string> no_deps;
const char* no_message = "";
- const char* no_current_dir = nullptr;
- const cmPolicies::PolicyStatus cmp0116_new = cmPolicies::NEW;
- std::vector<std::string> no_byproducts;
std::vector<std::string> outputs;
outputs.push_back(configGenex(
cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb")));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetCommandLines(commandLines);
+ cc->SetComment(no_message);
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetStdPipesUTF8(true);
+
if (this->GetGlobalGenerator()->IsVisualStudio()) {
+ cc->SetByproducts(outputs);
this->AddCustomCommandToTarget(
- target->GetName(), outputs, no_deps, commandLines,
- cmCustomCommandType::PRE_BUILD, no_message, no_current_dir, cmp0116_new,
- true, false, "", "", false, cmObjectLibraryCommands::Accept,
- stdPipesUTF8);
+ target->GetName(), cmCustomCommandType::PRE_BUILD, std::move(cc),
+ cmObjectLibraryCommands::Accept);
} else {
- cmImplicitDependsList no_implicit_depends;
- cmSourceFile* copy_rule = this->AddCustomCommandToOutput(
- outputs, no_byproducts, no_deps, no_main_dependency, no_implicit_depends,
- commandLines, no_message, no_current_dir, cmp0116_new, false, true,
- false, false, "", "", stdPipesUTF8);
+ cc->SetOutputs(outputs);
+ cmSourceFile* copy_rule = this->AddCustomCommandToOutput(std::move(cc));
if (copy_rule) {
target->AddSource(copy_rule->ResolveFullPath());
@@ -2808,10 +2767,47 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,
}
}
-void cmLocalGenerator::IncludeFileInUnitySources(
- cmGeneratedFileStream& unity_file, std::string const& sf_full_path,
- cmValue beforeInclude, cmValue afterInclude, cmValue uniqueIdName) const
+cmLocalGenerator::UnitySource cmLocalGenerator::WriteUnitySource(
+ cmGeneratorTarget* target, std::vector<std::string> const& configs,
+ cmRange<std::vector<UnityBatchedSource>::const_iterator> sources,
+ cmValue beforeInclude, cmValue afterInclude, std::string filename) const
+{
+ cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
+ cmGeneratedFileStream file(
+ filename, false, target->GetGlobalGenerator()->GetMakefileEncoding());
+ file.SetCopyIfDifferent(true);
+ file << "/* generated by CMake */\n\n";
+
+ bool perConfig = false;
+ for (UnityBatchedSource const& ubs : sources) {
+ cm::optional<std::string> cond;
+ if (ubs.Configs.size() != configs.size()) {
+ perConfig = true;
+ cond = std::string();
+ cm::string_view sep;
+ for (size_t ci : ubs.Configs) {
+ cond = cmStrCat(*cond, sep, "defined(CMAKE_UNITY_CONFIG_",
+ cmSystemTools::UpperCase(configs[ci]), ")");
+ sep = " || "_s;
+ }
+ }
+ RegisterUnitySources(target, ubs.Source, filename);
+ WriteUnitySourceInclude(file, cond, ubs.Source->ResolveFullPath(),
+ beforeInclude, afterInclude, uniqueIdName);
+ }
+
+ return UnitySource(std::move(filename), perConfig);
+}
+
+void cmLocalGenerator::WriteUnitySourceInclude(
+ std::ostream& unity_file, cm::optional<std::string> const& cond,
+ std::string const& sf_full_path, cmValue beforeInclude, cmValue afterInclude,
+ cmValue uniqueIdName) const
{
+ if (cond) {
+ unity_file << "#if " << *cond << "\n";
+ }
+
if (cmNonempty(uniqueIdName)) {
std::string pathToHash;
auto PathEqOrSubDir = [](std::string const& a, std::string const& b) {
@@ -2831,7 +2827,10 @@ void cmLocalGenerator::IncludeFileInUnitySources(
unity_file << "/* " << pathToHash << " */\n"
<< "#undef " << *uniqueIdName << "\n"
<< "#define " << *uniqueIdName << " unity_"
- << cmSystemTools::ComputeStringMD5(pathToHash) << "\n";
+#ifndef CMAKE_BOOTSTRAP
+ << cmSystemTools::ComputeStringMD5(pathToHash) << "\n"
+#endif
+ ;
}
if (beforeInclude) {
@@ -2843,21 +2842,25 @@ void cmLocalGenerator::IncludeFileInUnitySources(
if (afterInclude) {
unity_file << *afterInclude << "\n";
}
+ if (cond) {
+ unity_file << "#endif\n";
+ }
unity_file << "\n";
}
-std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
+std::vector<cmLocalGenerator::UnitySource>
+cmLocalGenerator::AddUnityFilesModeAuto(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
- cmValue afterInclude, std::string const& filename_base, size_t batchSize)
+ std::vector<std::string> const& configs,
+ std::vector<UnityBatchedSource> const& filtered_sources,
+ cmValue beforeInclude, cmValue afterInclude,
+ std::string const& filename_base, size_t batchSize)
{
if (batchSize == 0) {
batchSize = filtered_sources.size();
}
- cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
-
- std::vector<std::string> unity_files;
+ std::vector<UnitySource> unity_files;
for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
itemsLeft > 0; itemsLeft -= chunk, ++batch) {
@@ -2865,74 +2868,48 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
std::string filename = cmStrCat(filename_base, "unity_", batch,
(lang == "C") ? "_c.c" : "_cxx.cxx");
-
- const std::string filename_tmp = cmStrCat(filename, ".tmp");
- {
- size_t begin = batch * batchSize;
- size_t end = begin + chunk;
-
- cmGeneratedFileStream file(
- filename_tmp, false,
- target->GetGlobalGenerator()->GetMakefileEncoding());
- file << "/* generated by CMake */\n\n";
-
- for (; begin != end; ++begin) {
- cmSourceFile* sf = filtered_sources[begin];
- RegisterUnitySources(target, sf, filename);
- IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
- afterInclude, uniqueIdName);
- }
- }
- cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
- unity_files.emplace_back(std::move(filename));
+ auto const begin = filtered_sources.begin() + batch * batchSize;
+ auto const end = begin + chunk;
+ unity_files.emplace_back(this->WriteUnitySource(
+ target, configs, cmMakeRange(begin, end), beforeInclude, afterInclude,
+ std::move(filename)));
}
return unity_files;
}
-std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
+std::vector<cmLocalGenerator::UnitySource>
+cmLocalGenerator::AddUnityFilesModeGroup(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
- cmValue afterInclude, std::string const& filename_base)
+ std::vector<std::string> const& configs,
+ std::vector<UnityBatchedSource> const& filtered_sources,
+ cmValue beforeInclude, cmValue afterInclude,
+ std::string const& filename_base)
{
- std::vector<std::string> unity_files;
+ std::vector<UnitySource> unity_files;
// sources organized by group name. Drop any source
// without a group
- std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping;
- for (cmSourceFile* sf : filtered_sources) {
- if (cmValue value = sf->GetProperty("UNITY_GROUP")) {
+ std::unordered_map<std::string, std::vector<UnityBatchedSource>>
+ explicit_mapping;
+ for (UnityBatchedSource const& ubs : filtered_sources) {
+ if (cmValue value = ubs.Source->GetProperty("UNITY_GROUP")) {
auto i = explicit_mapping.find(*value);
if (i == explicit_mapping.end()) {
- std::vector<cmSourceFile*> sources{ sf };
- explicit_mapping.emplace(*value, sources);
+ std::vector<UnityBatchedSource> sources{ ubs };
+ explicit_mapping.emplace(*value, std::move(sources));
} else {
- i->second.emplace_back(sf);
+ i->second.emplace_back(ubs);
}
}
}
- cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
-
for (auto const& item : explicit_mapping) {
auto const& name = item.first;
std::string filename = cmStrCat(filename_base, "unity_", name,
(lang == "C") ? "_c.c" : "_cxx.cxx");
-
- const std::string filename_tmp = cmStrCat(filename, ".tmp");
- {
- cmGeneratedFileStream file(
- filename_tmp, false,
- target->GetGlobalGenerator()->GetMakefileEncoding());
- file << "/* generated by CMake */\n\n";
-
- for (cmSourceFile* sf : item.second) {
- RegisterUnitySources(target, sf, filename);
- IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude,
- afterInclude, uniqueIdName);
- }
- }
- cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
- unity_files.emplace_back(std::move(filename));
+ unity_files.emplace_back(this->WriteUnitySource(
+ target, configs, cmMakeRange(item.second), beforeInclude, afterInclude,
+ std::move(filename)));
}
return unity_files;
@@ -2944,20 +2921,33 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
return;
}
- // FIXME: Handle all configurations in multi-config generators.
- std::string config;
- if (!this->GetGlobalGenerator()->IsMultiConfig()) {
- config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ std::vector<UnityBatchedSource> unitySources;
+
+ std::vector<std::string> configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
+ std::map<cmSourceFile const*, size_t> index;
+
+ for (size_t ci = 0; ci < configs.size(); ++ci) {
+ // FIXME: Refactor collection of sources to not evaluate object libraries.
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, configs[ci]);
+ for (cmSourceFile* sf : sources) {
+ auto mi = index.find(sf);
+ if (mi == index.end()) {
+ unitySources.emplace_back(sf);
+ std::map<cmSourceFile const*, size_t>::value_type entry(
+ sf, unitySources.size() - 1);
+ mi = index.insert(entry).first;
+ }
+ unitySources[mi->second].Configs.emplace_back(ci);
+ }
}
std::string filename_base =
cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/",
target->GetName(), ".dir/Unity/");
- // FIXME: Refactor collection of sources to not evaluate object libraries.
- std::vector<cmSourceFile*> sources;
- target->GetSourceFiles(sources, config);
-
cmValue batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE");
const size_t unityBatchSize = batchSizeString
? static_cast<size_t>(std::atoi(batchSizeString->c_str()))
@@ -2969,9 +2959,11 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
cmValue unityMode = target->GetProperty("UNITY_BUILD_MODE");
for (std::string lang : { "C", "CXX" }) {
- std::vector<cmSourceFile*> filtered_sources;
- std::copy_if(sources.begin(), sources.end(),
- std::back_inserter(filtered_sources), [&](cmSourceFile* sf) {
+ std::vector<UnityBatchedSource> filtered_sources;
+ std::copy_if(unitySources.begin(), unitySources.end(),
+ std::back_inserter(filtered_sources),
+ [&](UnityBatchedSource const& ubs) -> bool {
+ cmSourceFile* sf = ubs.Source;
return sf->GetLanguage() == lang &&
!sf->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION") &&
!sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
@@ -2981,15 +2973,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
!sf->GetProperty("INCLUDE_DIRECTORIES");
});
- std::vector<std::string> unity_files;
+ std::vector<UnitySource> unity_files;
if (!unityMode || *unityMode == "BATCH") {
- unity_files =
- AddUnityFilesModeAuto(target, lang, filtered_sources, beforeInclude,
- afterInclude, filename_base, unityBatchSize);
+ unity_files = AddUnityFilesModeAuto(
+ target, lang, configs, filtered_sources, beforeInclude, afterInclude,
+ filename_base, unityBatchSize);
} else if (unityMode && *unityMode == "GROUP") {
unity_files =
- AddUnityFilesModeGroup(target, lang, filtered_sources, beforeInclude,
- afterInclude, filename_base);
+ AddUnityFilesModeGroup(target, lang, configs, filtered_sources,
+ beforeInclude, afterInclude, filename_base);
} else {
// unity mode is set to an unsupported value
std::string e("Invalid UNITY_BUILD_MODE value of " + *unityMode +
@@ -2998,11 +2990,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
this->IssueMessage(MessageType::FATAL_ERROR, e);
}
- for (auto const& file : unity_files) {
- auto* unity = this->GetMakefile()->GetOrCreateSource(file);
- target->AddSource(file, true);
+ for (UnitySource const& file : unity_files) {
+ auto* unity = this->GetMakefile()->GetOrCreateSource(file.Path);
+ target->AddSource(file.Path, true);
unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
- unity->SetProperty("UNITY_SOURCE_FILE", file);
+ unity->SetProperty("UNITY_SOURCE_FILE", file.Path);
+ if (file.PerConfig) {
+ unity->SetProperty("COMPILE_DEFINITIONS",
+ "CMAKE_UNITY_CONFIG_$<UPPER_CASE:$<CONFIG>>");
+ }
}
}
}
@@ -3439,21 +3435,27 @@ void cmLocalGenerator::GenerateTargetInstallRules(
static bool cmLocalGeneratorShortenObjectName(std::string& objName,
std::string::size_type max_len)
{
+ // Check if the path can be shortened using an md5 sum replacement for
+ // a portion of the path.
+ std::string::size_type md5Len = 32;
+ std::string::size_type numExtraChars = objName.size() - max_len + md5Len;
+ std::string::size_type pos = objName.find('/', numExtraChars);
+ if (pos == std::string::npos) {
+ pos = objName.rfind('/', numExtraChars);
+ if (pos == std::string::npos || pos <= md5Len) {
+ return false;
+ }
+ }
+
// 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 != std::string::npos) {
- cmCryptoHash md5(cmCryptoHash::AlgoMD5);
- std::string md5name = cmStrCat(md5.HashString(objName.substr(0, pos)),
- cm::string_view(objName).substr(pos));
- objName = md5name;
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ std::string md5name = cmStrCat(md5.HashString(objName.substr(0, pos)),
+ cm::string_view(objName).substr(pos));
+ objName = md5name;
- // The object name is now short enough.
- return true;
- }
- // The object name could not be shortened enough.
- return false;
+ // The object name is now shorter, check if it is short enough.
+ return pos >= numExtraChars;
}
bool cmLocalGeneratorCheckObjectName(std::string& objName,
@@ -3505,7 +3507,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
bool done;
int cc = 0;
char rpstr[100];
- sprintf(rpstr, "_p_");
+ snprintf(rpstr, sizeof(rpstr), "_p_");
cmSystemTools::ReplaceString(ssin, "+", rpstr);
std::string sssin = sin;
do {
@@ -3521,7 +3523,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
}
sssin = ssin;
cmSystemTools::ReplaceString(ssin, "_p_", rpstr);
- sprintf(rpstr, "_p%d_", cc++);
+ snprintf(rpstr, sizeof(rpstr), "_p%d_", cc++);
} while (!done);
}
@@ -4015,23 +4017,20 @@ std::string ComputeCustomCommandRuleFileName(cmLocalGenerator& lg,
h.HashString(output).substr(0, 16));
}
-cmSourceFile* AddCustomCommand(
- cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116)
+cmSourceFile* AddCustomCommand(cmLocalGenerator& lg, cmCommandOrigin origin,
+ std::unique_ptr<cmCustomCommand> cc,
+ bool replace)
{
cmMakefile* mf = lg.GetMakefile();
+ const auto& lfbt = cc->GetBacktrace();
+ const auto& outputs = cc->GetOutputs();
+ const auto& byproducts = cc->GetByproducts();
+ const auto& commandLines = cc->GetCommandLines();
// Choose a source file on which to store the custom command.
cmSourceFile* file = nullptr;
- if (!commandLines.empty() && !main_dependency.empty()) {
+ if (!commandLines.empty() && cc->HasMainDependency()) {
+ const auto& main_dependency = cc->GetMainDependency();
// The main dependency was specified. Use it unless a different
// custom command already used it.
file = mf->GetSource(main_dependency);
@@ -4081,29 +4080,14 @@ cmSourceFile* AddCustomCommand(
// Attach the custom command to the file.
if (file) {
- // Construct a complete list of dependencies.
- std::vector<std::string> depends2(depends);
- if (!main_dependency.empty()) {
- depends2.push_back(main_dependency);
- }
-
- std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
- outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir,
- stdPipesUTF8);
- cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
- cc->SetImplicitDepends(implicit_depends);
- cc->SetUsesTerminal(uses_terminal);
- cc->SetCommandExpandLists(command_expand_lists);
- cc->SetDepfile(depfile);
- cc->SetJobPool(job_pool);
- cc->SetCMP0116Status(cmp0116);
- file->SetCustomCommand(std::move(cc));
lg.AddSourceOutputs(file, outputs, cmLocalGenerator::OutputRole::Primary,
lfbt, origin);
lg.AddSourceOutputs(file, byproducts,
cmLocalGenerator::OutputRole::Byproduct, lfbt, origin);
+
+ file->SetCustomCommand(std::move(cc));
}
return file;
}
@@ -4132,63 +4116,38 @@ bool AnyTargetCommandOutputMatches(
}
namespace detail {
-void AddCustomCommandToTarget(cmLocalGenerator& lg,
- const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, cmTarget* target,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- cmCustomCommandType type, const char* comment,
- const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile,
- const std::string& job_pool,
- bool command_expand_lists, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116)
+void AddCustomCommandToTarget(cmLocalGenerator& lg, cmCommandOrigin origin,
+ cmTarget* target, cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc)
{
// Add the command to the appropriate build step for the target.
- std::vector<std::string> no_output;
- cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt,
- comment, workingDir, stdPipesUTF8);
- cc.SetEscapeOldStyle(escapeOldStyle);
- cc.SetEscapeAllowMakeVars(true);
- cc.SetUsesTerminal(uses_terminal);
- cc.SetCommandExpandLists(command_expand_lists);
- cc.SetDepfile(depfile);
- cc.SetJobPool(job_pool);
- cc.SetCMP0116Status(cmp0116);
- cc.SetTarget(target->GetName());
+ cc->SetEscapeAllowMakeVars(true);
+ cc->SetTarget(target->GetName());
+
+ lg.AddTargetByproducts(target, cc->GetByproducts(), cc->GetBacktrace(),
+ origin);
+
switch (type) {
case cmCustomCommandType::PRE_BUILD:
- target->AddPreBuildCommand(std::move(cc));
+ target->AddPreBuildCommand(std::move(*cc));
break;
case cmCustomCommandType::PRE_LINK:
- target->AddPreLinkCommand(std::move(cc));
+ target->AddPreLinkCommand(std::move(*cc));
break;
case cmCustomCommandType::POST_BUILD:
- target->AddPostBuildCommand(std::move(cc));
+ target->AddPostBuildCommand(std::move(*cc));
break;
}
- lg.AddTargetByproducts(target, byproducts, lfbt, origin);
+ cc.reset();
}
-cmSourceFile* AddCustomCommandToOutput(
- cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116)
+cmSourceFile* AddCustomCommandToOutput(cmLocalGenerator& lg,
+ cmCommandOrigin origin,
+ std::unique_ptr<cmCustomCommand> cc,
+ bool replace)
{
- return AddCustomCommand(lg, lfbt, origin, outputs, byproducts, depends,
- main_dependency, implicit_depends, commandLines,
- comment, workingDir, replace, escapeOldStyle,
- uses_terminal, command_expand_lists, depfile,
- job_pool, stdPipesUTF8, cmp0116);
+ return AddCustomCommand(lg, origin, std::move(cc), replace);
}
void AppendCustomCommandToOutput(cmLocalGenerator& lg,
@@ -4231,33 +4190,25 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
lfbt);
}
-void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, cmTarget* target,
- const char* workingDir,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- bool escapeOldStyle, const char* comment,
- bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116)
+void AddUtilityCommand(cmLocalGenerator& lg, cmCommandOrigin origin,
+ cmTarget* target, std::unique_ptr<cmCustomCommand> cc)
{
+ // They might be moved away
+ auto byproducts = cc->GetByproducts();
+ auto lfbt = cc->GetBacktrace();
+
// Use an empty comment to avoid generation of default comment.
- if (!comment) {
- comment = "";
+ if (!cc->GetComment()) {
+ cc->SetComment("");
}
// Create the generated symbolic output name of the utility target.
std::string output =
lg.CreateUtilityOutput(target->GetName(), byproducts, lfbt);
+ cc->SetOutputs(output);
- std::string no_main_dependency;
- cmImplicitDependsList no_implicit_depends;
- cmSourceFile* rule = AddCustomCommand(
- lg, lfbt, origin, { output }, byproducts, depends, no_main_dependency,
- no_implicit_depends, commandLines, comment, workingDir,
- /*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
- /*depfile=*/"", job_pool, stdPipesUTF8, cmp0116);
+ cmSourceFile* rule = AddCustomCommand(lg, origin, std::move(cc),
+ /*replace=*/false);
if (rule) {
lg.AddTargetByproducts(target, byproducts, lfbt, origin);
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 3614c84..115a54a 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -11,8 +11,11 @@
#include <set>
#include <string>
#include <unordered_map>
+#include <utility>
#include <vector>
+#include <cm/optional>
+
#include <cm3p/kwiml/int.h>
#include "cmCustomCommandTypes.h"
@@ -28,7 +31,6 @@ class cmComputeLinkInformation;
class cmCustomCommand;
class cmCustomCommandGenerator;
class cmCustomCommandLines;
-class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmImplicitDependsList;
@@ -40,6 +42,9 @@ class cmState;
class cmTarget;
class cmake;
+template <typename Iter>
+class cmRange;
+
/** Flag if byproducts shall also be considered. */
enum class cmSourceOutputKind
{
@@ -174,18 +179,12 @@ public:
bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target,
const std::string& lang);
- enum class IncludePathStyle
- {
- Default,
- Absolute,
- };
-
//! Get the include flags for the current makefile and language
- std::string GetIncludeFlags(
- std::vector<std::string> const& includes, cmGeneratorTarget* target,
- std::string const& lang, std::string const& config,
- bool forResponseFile = false,
- IncludePathStyle pathStyle = IncludePathStyle::Default);
+ std::string GetIncludeFlags(std::vector<std::string> const& includes,
+ cmGeneratorTarget* target,
+ std::string const& lang,
+ std::string const& config,
+ bool forResponseFile = false);
using GeneratorTargetVector =
std::vector<std::unique_ptr<cmGeneratorTarget>>;
@@ -194,6 +193,11 @@ public:
return this->GeneratorTargets;
}
+ const GeneratorTargetVector& GetOwnedImportedGeneratorTargets() const
+ {
+ return this->OwnedImportedGeneratorTargets;
+ }
+
void AddGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt);
void AddImportedGeneratorTarget(cmGeneratorTarget* gt);
void AddOwnedImportedGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt);
@@ -324,53 +328,23 @@ public:
* Add a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a target.
*/
cmTarget* AddCustomCommandToTarget(
- const std::string& target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir,
- cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle = true,
- bool uses_terminal = false, const std::string& depfile = "",
- const std::string& job_pool = "", bool command_expand_lists = false,
- cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject,
- bool stdPipesUTF8 = false);
+ const std::string& target, cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc,
+ cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject);
/**
* Add a custom command to a source file.
*/
- cmSourceFile* 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, cmPolicies::PolicyStatus cmp0116,
- bool replace = false, bool escapeOldStyle = true,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "", const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
- cmSourceFile* AddCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, cmPolicies::PolicyStatus cmp0116,
- bool replace = false, bool escapeOldStyle = true,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "", const std::string& job_pool = "",
- bool stdPipesUTF8 = false);
+ cmSourceFile* AddCustomCommandToOutput(std::unique_ptr<cmCustomCommand> cc,
+ bool replace = false);
/**
* Add a utility to the build. A utility target is a command that is run
* every time the target is built.
*/
- cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
- const char* workingDir, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
- bool escapeOldStyle = true, const char* comment = nullptr,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& job_pool = "", bool stdPipesUTF8 = false);
+ cmTarget* AddUtilityCommand(const std::string& utilityName,
+ bool excludeFromAll,
+ std::unique_ptr<cmCustomCommand> cc);
virtual std::string CreateUtilityOutput(
std::string const& targetName, std::vector<std::string> const& byproducts,
@@ -496,7 +470,7 @@ public:
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
- void GetDeviceLinkFlags(cmLinkLineComputer* linkLineComputer,
+ void GetDeviceLinkFlags(cmLinkLineComputer& linkLineComputer,
const std::string& config, std::string& linkLibs,
std::string& linkFlags, std::string& frameworkPath,
std::string& linkPath, cmGeneratorTarget* target);
@@ -550,12 +524,11 @@ public:
cmValue GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
protected:
- // The default implementation ignores the IncludePathStyle and always
- // uses absolute paths. A generator may override this to use relative
- // paths in some cases.
+ // The default implementation converts to a Windows shortpath to
+ // help older toolchains handle spaces and such. A generator may
+ // override this to avoid that conversion.
virtual std::string ConvertToIncludeReference(
- std::string const& path, IncludePathStyle pathStyle,
- cmOutputConverter::OutputFormat format);
+ std::string const& path, cmOutputConverter::OutputFormat format);
//! put all the libraries for a target on into the given stream
void OutputLinkLibraries(cmComputeLinkInformation* pcli,
@@ -657,18 +630,48 @@ private:
const std::string& ReuseFrom,
cmGeneratorTarget* reuseTarget,
std::vector<std::string> const& extensions);
- void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
- std::string const& sf_full_path,
- cmValue beforeInclude, cmValue afterInclude,
- cmValue uniqueIdName) const;
- std::vector<std::string> AddUnityFilesModeAuto(
+
+ struct UnityBatchedSource
+ {
+ cmSourceFile* Source = nullptr;
+ std::vector<size_t> Configs;
+ UnityBatchedSource(cmSourceFile* sf)
+ : Source(sf)
+ {
+ }
+ };
+ struct UnitySource
+ {
+ std::string Path;
+ bool PerConfig = false;
+ UnitySource(std::string path, bool perConfig)
+ : Path(std::move(path))
+ , PerConfig(perConfig)
+ {
+ }
+ };
+
+ UnitySource WriteUnitySource(
+ cmGeneratorTarget* target, std::vector<std::string> const& configs,
+ cmRange<std::vector<UnityBatchedSource>::const_iterator> sources,
+ cmValue beforeInclude, cmValue afterInclude, std::string filename) const;
+ void WriteUnitySourceInclude(std::ostream& unity_file,
+ cm::optional<std::string> const& cond,
+ std::string const& sf_full_path,
+ cmValue beforeInclude, cmValue afterInclude,
+ cmValue uniqueIdName) const;
+ std::vector<UnitySource> AddUnityFilesModeAuto(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
- cmValue afterInclude, std::string const& filename_base, size_t batchSize);
- std::vector<std::string> AddUnityFilesModeGroup(
+ std::vector<std::string> const& configs,
+ std::vector<UnityBatchedSource> const& filtered_sources,
+ cmValue beforeInclude, cmValue afterInclude,
+ std::string const& filename_base, size_t batchSize);
+ std::vector<UnitySource> AddUnityFilesModeGroup(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
- cmValue afterInclude, std::string const& filename_base);
+ std::vector<std::string> const& configs,
+ std::vector<UnityBatchedSource> const& filtered_sources,
+ cmValue beforeInclude, cmValue afterInclude,
+ std::string const& filename_base);
};
#if !defined(CMAKE_BOOTSTRAP)
@@ -678,30 +681,14 @@ bool cmLocalGeneratorCheckObjectName(std::string& objName,
#endif
namespace detail {
-void AddCustomCommandToTarget(cmLocalGenerator& lg,
- const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, cmTarget* target,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- cmCustomCommandType type, const char* comment,
- const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile,
- const std::string& job_pool,
- bool command_expand_lists, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116);
-
-cmSourceFile* AddCustomCommandToOutput(
- cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116);
+void AddCustomCommandToTarget(cmLocalGenerator& lg, cmCommandOrigin origin,
+ cmTarget* target, cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc);
+
+cmSourceFile* AddCustomCommandToOutput(cmLocalGenerator& lg,
+ cmCommandOrigin origin,
+ std::unique_ptr<cmCustomCommand> cc,
+ bool replace);
void AppendCustomCommandToOutput(cmLocalGenerator& lg,
const cmListFileBacktrace& lfbt,
@@ -710,16 +697,8 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines);
-void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
- cmCommandOrigin origin, cmTarget* target,
- const char* workingDir,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- bool escapeOldStyle, const char* comment,
- bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool, bool stdPipesUTF8,
- cmPolicies::PolicyStatus cmp0116);
+void AddUtilityCommand(cmLocalGenerator& lg, cmCommandOrigin origin,
+ cmTarget* target, std::unique_ptr<cmCustomCommand> cc);
std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target);
std::vector<std::string> ComputeISPCExtraObjects(
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 8556fe6..106f76b 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -205,11 +205,8 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
// Virtual protected methods.
std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
- std::string const& path, IncludePathStyle pathStyle,
- cmOutputConverter::OutputFormat format)
+ std::string const& path, cmOutputConverter::OutputFormat format)
{
- // FIXME: Remove IncludePathStyle infrastructure. It is no longer used.
- static_cast<void>(pathStyle);
return this->ConvertToOutputFormat(path, format);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 6404037..3118bb4 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -12,7 +12,6 @@
#include "cmListFileCache.h"
#include "cmLocalCommonGenerator.h"
-#include "cmLocalGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
@@ -93,8 +92,7 @@ public:
protected:
std::string ConvertToIncludeReference(
- std::string const& path, IncludePathStyle pathStyle,
- cmOutputConverter::OutputFormat format) override;
+ std::string const& path, cmOutputConverter::OutputFormat format) override;
private:
cmGeneratedFileStream& GetImplFileStream(const std::string& config) const;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 7e39b91..0f8cdca 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1274,12 +1274,12 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
cmSystemTools::ReplaceString(ret, "-", "__");
cmSystemTools::ReplaceString(ret, "+", "___");
int ni = 0;
- char buffer[5];
+ char buffer[12];
// 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) {
++ni;
- sprintf(buffer, "%04d", ni);
+ snprintf(buffer, sizeof(buffer), "%04d", ni);
ret = unmodified + buffer;
}
this->ShortMakeVariableMap[ret] = "1";
@@ -1302,13 +1302,13 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
if (static_cast<int>(str1.size()) + static_cast<int>(str2.size()) > size) {
str1 = str1.substr(0, size - str2.size());
}
- char buffer[5];
+ char buffer[12];
int ni = 0;
- sprintf(buffer, "%04d", ni);
+ snprintf(buffer, sizeof(buffer), "%04d", ni);
ret = str1 + str2 + buffer;
while (this->ShortMakeVariableMap.count(ret) && ni < 1000) {
++ni;
- sprintf(buffer, "%04d", ni);
+ snprintf(buffer, sizeof(buffer), "%04d", ni);
ret = str1 + str2 + buffer;
}
if (ni == 1000) {
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 3ed49a0..4c0d2eea 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -2,18 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio10Generator.h"
-#include <cmext/algorithm>
-
#include <cm3p/expat.h>
-#include "cmAlgorithms.h"
-#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio10Generator.h"
-#include "cmMakefile.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmVisualStudio10TargetGenerator.h"
#include "cmXMLParser.h"
#include "cmake.h"
+class cmGeneratorTarget;
+
class cmVS10XMLParser : public cmXMLParser
{
public:
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 45ee082..75fe262 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -8,6 +8,7 @@
#include "cmLocalVisualStudio7Generator.h"
+class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 96dda53..ed7e888 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -2,26 +2,45 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio7Generator.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <functional>
+#include <sstream>
+#include <utility>
+
#include <cm/memory>
#include <cmext/algorithm>
#include <windows.h>
#include <cm3p/expat.h>
-#include <ctype.h> // for isspace
+
+#include "cmsys/FStream.hxx"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio7Generator.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
-#include "cmMessageType.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
#include "cmSourceFile.h"
+#include "cmSourceGroup.h"
+#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
+#include "cmValue.h"
+#include "cmVsProjectType.h"
#include "cmXMLParser.h"
#include "cmake.h"
@@ -109,19 +128,21 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
const auto& tgts = this->GetGeneratorTargets();
for (auto& l : tgts) {
if (l->GetType() == cmStateEnums::GLOBAL_TARGET) {
- std::vector<std::string> no_depends;
cmCustomCommandLines force_commands =
cmMakeSingleCommandLine({ "cd", "." });
- std::string no_main_dependency;
std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
"/CMakeFiles/", l->GetName(), "_force");
if (cmSourceFile* sf =
this->Makefile->GetOrCreateGeneratedSource(force)) {
sf->SetProperty("SYMBOLIC", "1");
}
- if (cmSourceFile* file = this->AddCustomCommandToOutput(
- force, no_depends, no_main_dependency, force_commands, " ",
- nullptr, cmPolicies::NEW, true)) {
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(force);
+ cc->SetCommandLines(force_commands);
+ cc->SetComment(" ");
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ if (cmSourceFile* file =
+ this->AddCustomCommandToOutput(std::move(cc), true)) {
l->AddSource(file->ResolveFullPath());
}
}
@@ -177,8 +198,8 @@ void cmLocalVisualStudio7Generator::GenerateTarget(cmGeneratorTarget* target)
// Intel Fortran for VS10 uses VS9 format ".vfproj" files.
cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion();
if (this->FortranProject &&
- gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS10) {
- gg->SetVersion(cmGlobalVisualStudioGenerator::VS9);
+ gg->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
+ gg->SetVersion(cmGlobalVisualStudioGenerator::VSVersion::VS9);
}
// add to the list of projects
@@ -239,16 +260,20 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
std::string argB = cmStrCat("-B", this->GetBinaryDirectory());
std::string stampName =
cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp");
- bool stdPipesUTF8 = true;
cmCustomCommandLines commandLines =
cmMakeSingleCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB,
"--check-stamp-file", stampName });
std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
- const char* no_working_directory = nullptr;
- this->AddCustomCommandToOutput(stampName, listFiles, makefileIn,
- commandLines, comment.c_str(),
- no_working_directory, cmPolicies::NEW, true,
- false, false, false, "", "", stdPipesUTF8);
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(stampName);
+ cc->SetMainDependency(makefileIn);
+ cc->SetDepends(listFiles);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment(comment.c_str());
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetStdPipesUTF8(true);
+ this->AddCustomCommandToOutput(std::move(cc), true);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
// Finalize the source file path now since we're adding this after
// the generator validated all project-named sources.
@@ -546,7 +571,17 @@ public:
this->First = true;
this->Stream << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"";
}
- void Finish() { this->Stream << (this->First ? "" : "\"") << "/>\n"; }
+ void Finish()
+ {
+ // If any commands were generated, finish constructing them.
+ if (!this->First) {
+ std::string finishScript =
+ this->LG->FinishConstructScript(VsProjectType::vcxproj);
+ this->Stream << this->LG->EscapeForXML(finishScript) << "\"";
+ }
+
+ this->Stream << "/>\n";
+ }
void Write(std::vector<cmCustomCommand> const& ccs)
{
for (cmCustomCommand const& command : ccs) {
@@ -1071,7 +1106,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
}
if (this->WindowsCEProject) {
- if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) {
+ if (this->GetVersion() <
+ cmGlobalVisualStudioGenerator::VSVersion::VS9) {
fout << "\t\t\t\tSubSystem=\"9\"\n";
} else {
fout << "\t\t\t\tSubSystem=\"8\"\n";
@@ -1148,7 +1184,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
}
if (this->WindowsCEProject) {
- if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) {
+ if (this->GetVersion() <
+ cmGlobalVisualStudioGenerator::VSVersion::VS9) {
fout << "\t\t\t\tSubSystem=\"9\"\n";
} else {
fout << "\t\t\t\tSubSystem=\"8\"\n";
@@ -1784,6 +1821,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
if (this->FortranProject) {
cmSystemTools::ReplaceString(script, "$(Configuration)", config);
}
+ script += this->FinishConstructScript(VsProjectType::vcxproj);
/* clang-format off */
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << customTool << "\"\n"
@@ -1990,7 +2028,8 @@ void cmLocalVisualStudio7Generator::WriteProjectStart(
<< "<VisualStudioProject\n"
<< "\tProjectType=\"Visual C++\"\n";
/* clang-format on */
- fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n";
+ fout << "\tVersion=\"" << (static_cast<uint16_t>(gg->GetVersion()) / 10)
+ << ".00\"\n";
cmValue p = target->GetProperty("PROJECT_LABEL");
const std::string projLabel = p ? *p : libName;
p = target->GetProperty("VS_KEYWORD");
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 6e06c09..d95ebc2 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -5,7 +5,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <map>
#include <memory>
+#include <set>
#include <string>
#include <vector>
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 03213ef..93f01ed 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -2,15 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudioGenerator.h"
+#include <utility>
+
#include "windows.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmSourceFile.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator(
cmGlobalGenerator* gg, cmMakefile* mf)
@@ -99,15 +105,11 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
}
// Add a pre-build event to create the directory.
- std::vector<std::string> no_output;
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
- bool stdPipesUTF8 = true;
cmCustomCommandLines commands = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir });
- pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands,
- cmListFileBacktrace(), nullptr, nullptr,
- stdPipesUTF8));
+ pcc.reset(new cmCustomCommand());
+ pcc->SetCommandLines(commands);
+ pcc->SetStdPipesUTF8(true);
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
@@ -241,3 +243,20 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
return script;
}
+
+std::string cmLocalVisualStudioGenerator::FinishConstructScript(
+ VsProjectType projectType, const std::string& newline)
+{
+ bool useLocal = this->CustomCommandUseLocal();
+
+ // Store the script in a string.
+ std::string script;
+
+ if (useLocal && projectType == VsProjectType::csproj) {
+ // This label is not provided by MSBuild for C# projects.
+ script += newline;
+ script += this->GetReportErrorLabel();
+ }
+
+ return script;
+}
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 91fb6b0..cf4f4d9 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -10,6 +10,7 @@
#include "cmGlobalVisualStudioGenerator.h"
#include "cmLocalGenerator.h"
+#include "cmVsProjectType.h"
class cmCustomCommand;
class cmCustomCommandGenerator;
@@ -30,9 +31,10 @@ public:
cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudioGenerator();
- /** Construct a script from the given list of command lines. */
std::string ConstructScript(cmCustomCommandGenerator const& ccg,
const std::string& newline = "\n");
+ std::string FinishConstructScript(VsProjectType projectType,
+ const std::string& newline = "\n");
/** Label to which to jump in a batch file after a failed step in a
sequence of custom commands. */
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 3b4e3a8..dd064a1 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -2,14 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalXCodeGenerator.h"
+#include <memory>
+#include <ostream>
+#include <utility>
+
#include "cmGeneratorTarget.h"
#include "cmGlobalXCodeGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
-class cmGeneratorTarget;
class cmGlobalGenerator;
-class cmMakefile;
cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 5f72f6d..ff6b356 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <iosfwd>
#include <map>
#include <string>
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
index 53112e0..4fcaedf 100644
--- a/Source/cmMachO.cxx
+++ b/Source/cmMachO.cxx
@@ -56,7 +56,7 @@ bool peek(cmsys::ifstream& fin, T& v)
template <typename T>
bool read(cmsys::ifstream& fin, T& v)
{
- return !!fin.read(reinterpret_cast<char*>(&v), sizeof(T));
+ return static_cast<bool>(fin.read(reinterpret_cast<char*>(&v), sizeof(T)));
}
// read from the file and fill multiple data structures where
@@ -68,7 +68,8 @@ bool read(cmsys::ifstream& fin, std::vector<T>& v)
if (v.empty()) {
return true;
}
- return !!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size());
+ return static_cast<bool>(
+ fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size()));
}
}
@@ -340,7 +341,8 @@ bool cmMachO::GetInstallName(std::string& install_name)
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);
+ uint32_t namelen = static_cast<uint32_t>(cmd.LoadCommand.size() -
+ sizeof(dylib_command));
install_name.assign(&cmd.LoadCommand[sizeof(dylib_command)], namelen);
return true;
}
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
index faa024b..ec7d54c 100644
--- a/Source/cmMachO.h
+++ b/Source/cmMachO.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <memory>
#include <string>
#if !defined(CMake_USE_MACH_PARSER)
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 8c4b2a7..154df63 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -77,7 +77,7 @@ bool cmMacroHelperCommand::operator()(
argVs.reserve(expandedArgs.size());
char argvName[60];
for (unsigned int j = 0; j < expandedArgs.size(); ++j) {
- sprintf(argvName, "${ARGV%u}", j);
+ snprintf(argvName, sizeof(argvName), "${ARGV%u}", j);
argVs.emplace_back(argvName);
}
// Invoke all the functions that were collected in the block.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 88f3cc7..94d3be6 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -79,7 +79,6 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
cmStateSnapshot const& snapshot)
: GlobalGenerator(globalGenerator)
, StateSnapshot(snapshot)
- , Backtrace(snapshot)
{
this->IsSourceFileTryCompile = false;
@@ -134,8 +133,8 @@ cmDirectoryId cmMakefile::GetDirectoryId() const
// If we ever need to expose this to CMake language code we should
// add a read-only property in cmMakefile::GetProperty.
char buf[32];
- sprintf(buf, "(%p)",
- static_cast<void const*>(this)); // cast avoids format warning
+ snprintf(buf, sizeof(buf), "(%p)",
+ static_cast<void const*>(this)); // cast avoids format warning
return std::string(buf);
}
@@ -340,7 +339,7 @@ public:
cm::optional<std::string> deferId, cmExecutionStatus& status)
: Makefile(mf)
{
- cmListFileContext const& lfc = cmListFileContext::FromCommandContext(
+ cmListFileContext const& lfc = cmListFileContext::FromListFileFunction(
lff, this->Makefile->StateSnapshot.GetExecutionListFile(),
std::move(deferId));
this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc);
@@ -891,12 +890,23 @@ struct file_not_persistent
};
}
-void cmMakefile::AddGeneratorAction(GeneratorAction action)
+void cmMakefile::AddGeneratorAction(GeneratorAction&& action)
{
assert(!this->GeneratorActionsInvoked);
this->GeneratorActions.emplace_back(std::move(action), this->Backtrace);
}
+void cmMakefile::GeneratorAction::operator()(cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt)
+{
+ if (cc) {
+ CCAction(lg, lfbt, std::move(cc));
+ } else {
+ assert(Action);
+ Action(lg, lfbt);
+ }
+}
+
void cmMakefile::DoGenerate(cmLocalGenerator& lg)
{
// do all the variable expansions here
@@ -904,7 +914,7 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg)
// give all the commands a chance to do something
// after the file has been parsed before generation
- for (const BT<GeneratorAction>& action : this->GeneratorActions) {
+ for (auto& action : this->GeneratorActions) {
action.Value(lg, action.Backtrace);
}
this->GeneratorActionsInvoked = true;
@@ -956,19 +966,6 @@ private:
cmListFileBacktrace& Backtrace;
cmListFileBacktrace Previous;
};
-
-cm::optional<std::string> MakeOptionalString(const char* str)
-{
- if (str) {
- return str;
- }
- return cm::nullopt;
-}
-
-const char* GetCStrOrNull(const cm::optional<std::string>& str)
-{
- return str ? str->c_str() : nullptr;
-}
}
bool cmMakefile::ValidateCustomCommand(
@@ -1056,14 +1053,12 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
}
cmTarget* cmMakefile::AddCustomCommandToTarget(
- const std::string& target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir,
- cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle, bool uses_terminal,
- const std::string& depfile, const std::string& job_pool,
- bool command_expand_lists, bool stdPipesUTF8)
+ const std::string& target, cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc)
{
+ const auto& byproducts = cc->GetByproducts();
+ const auto& commandLines = cc->GetCommandLines();
+
cmTarget* t = this->GetCustomCommandTarget(
target, cmObjectLibraryCommands::Reject, this->Backtrace);
@@ -1075,53 +1070,30 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
// Always create the byproduct sources and mark them generated.
this->CreateGeneratedOutputs(byproducts);
- // Strings could be moved into the callback function with C++14.
- cm::optional<std::string> commentStr = MakeOptionalString(comment);
- cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+ cc->SetCMP0116Status(this->GetPolicyStatus(cmPolicies::CMP0116));
// Dispatch command creation to allow generator expressions in outputs.
this->AddGeneratorAction(
- [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ std::move(cc),
+ [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ std::unique_ptr<cmCustomCommand> tcc) {
BacktraceGuard guard(this->Backtrace, lfbt);
- detail::AddCustomCommandToTarget(
- lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends,
- commandLines, type, GetCStrOrNull(commentStr),
- GetCStrOrNull(workingStr), escapeOldStyle, uses_terminal, depfile,
- job_pool, command_expand_lists, stdPipesUTF8, cmp0116);
+ tcc->SetBacktrace(lfbt);
+ detail::AddCustomCommandToTarget(lg, cmCommandOrigin::Project, t, type,
+ std::move(tcc));
});
return t;
}
void 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,
- cmPolicies::PolicyStatus cmp0116, const CommandSourceCallback& callback,
- bool replace, bool escapeOldStyle, bool uses_terminal,
- bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
-{
- std::vector<std::string> no_byproducts;
- cmImplicitDependsList no_implicit_depends;
- this->AddCustomCommandToOutput(
- { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
- commandLines, comment, workingDir, cmp0116, callback, replace,
- escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool,
- stdPipesUTF8);
-}
-
-void cmMakefile::AddCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, cmPolicies::PolicyStatus cmp0116,
- const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool, bool stdPipesUTF8)
+ std::unique_ptr<cmCustomCommand> cc, const CommandSourceCallback& callback,
+ bool replace)
{
+ const auto& outputs = cc->GetOutputs();
+ const auto& byproducts = cc->GetByproducts();
+ const auto& commandLines = cc->GetCommandLines();
+
// Make sure there is at least one output.
if (outputs.empty()) {
cmSystemTools::Error("Attempt to add a custom rule with no output!");
@@ -1137,20 +1109,17 @@ void cmMakefile::AddCustomCommandToOutput(
this->CreateGeneratedOutputs(outputs);
this->CreateGeneratedOutputs(byproducts);
- // Strings could be moved into the callback function with C++14.
- cm::optional<std::string> commentStr = MakeOptionalString(comment);
- cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+ cc->SetCMP0116Status(this->GetPolicyStatus(cmPolicies::CMP0116));
// Dispatch command creation to allow generator expressions in outputs.
this->AddGeneratorAction(
- [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ std::move(cc),
+ [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ std::unique_ptr<cmCustomCommand> tcc) {
BacktraceGuard guard(this->Backtrace, lfbt);
+ tcc->SetBacktrace(lfbt);
cmSourceFile* sf = detail::AddCustomCommandToOutput(
- lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends,
- main_dependency, implicit_depends, commandLines,
- GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace,
- escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool,
- stdPipesUTF8, cmp0116);
+ lg, cmCommandOrigin::Project, std::move(tcc), replace);
if (callback && sf) {
callback(sf);
}
@@ -1160,19 +1129,21 @@ void cmMakefile::AddCustomCommandToOutput(
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,
- cmPolicies::PolicyStatus cmp0116)
+ const cmCustomCommandLines& commandLines, const char* comment)
{
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetDepends(depends);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment(comment);
+
// Translate the old-style signature to one of the new-style
// signatures.
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.
- std::vector<std::string> no_byproducts;
- this->AddCustomCommandToTarget(
- target, no_byproducts, depends, commandLines,
- cmCustomCommandType::POST_BUILD, comment, nullptr, cmp0116);
+ this->AddCustomCommandToTarget(target, cmCustomCommandType::POST_BUILD,
+ std::move(cc));
return;
}
@@ -1204,20 +1175,19 @@ void cmMakefile::AddCustomCommandOldStyle(
if (sourceFiles.find(source)) {
// The source looks like a real file. Use it as the main dependency.
for (std::string const& output : outputs) {
- this->AddCustomCommandToOutput(output, depends, source, commandLines,
- comment, nullptr, cmp0116,
- addRuleFileToTarget);
+ auto cc1 = cm::make_unique<cmCustomCommand>(*cc);
+ cc1->SetOutputs(output);
+ cc1->SetMainDependency(source);
+ this->AddCustomCommandToOutput(std::move(cc1), addRuleFileToTarget);
}
} else {
- std::string no_main_dependency;
- std::vector<std::string> depends2 = depends;
- depends2.push_back(source);
+ cc->AppendDepends({ source });
// The source may not be a real file. Do not use a main dependency.
for (std::string const& output : outputs) {
- this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
- commandLines, comment, nullptr, cmp0116,
- addRuleFileToTarget);
+ auto cc1 = cm::make_unique<cmCustomCommand>(*cc);
+ cc1->SetOutputs(output);
+ this->AddCustomCommandToOutput(std::move(cc1), addRuleFileToTarget);
}
}
}
@@ -1239,14 +1209,13 @@ void cmMakefile::AppendCustomCommandToOutput(
}
}
-cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll, const char* workingDir,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
- bool escapeOldStyle, const char* comment, bool uses_terminal,
- bool command_expand_lists, const std::string& job_pool, bool stdPipesUTF8)
+cmTarget* cmMakefile::AddUtilityCommand(const std::string& utilityName,
+ bool excludeFromAll,
+ std::unique_ptr<cmCustomCommand> cc)
{
+ const auto& depends = cc->GetDepends();
+ const auto& byproducts = cc->GetByproducts();
+ const auto& commandLines = cc->GetCommandLines();
cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll);
// Validate custom commands.
@@ -1258,19 +1227,17 @@ cmTarget* cmMakefile::AddUtilityCommand(
// Always create the byproduct sources and mark them generated.
this->CreateGeneratedOutputs(byproducts);
- // Strings could be moved into the callback function with C++14.
- cm::optional<std::string> commentStr = MakeOptionalString(comment);
- cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+ cc->SetCMP0116Status(this->GetPolicyStatus(cmPolicies::CMP0116));
// Dispatch command creation to allow generator expressions in outputs.
this->AddGeneratorAction(
- [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ std::move(cc),
+ [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ std::unique_ptr<cmCustomCommand> tcc) {
BacktraceGuard guard(this->Backtrace, lfbt);
- detail::AddUtilityCommand(
- lg, lfbt, cmCommandOrigin::Project, target, GetCStrOrNull(workingStr),
- byproducts, depends, commandLines, escapeOldStyle,
- GetCStrOrNull(commentStr), uses_terminal, command_expand_lists,
- job_pool, stdPipesUTF8, cmp0116);
+ tcc->SetBacktrace(lfbt);
+ detail::AddUtilityCommand(lg, cmCommandOrigin::Project, target,
+ std::move(tcc));
});
return target;
@@ -4428,11 +4395,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
}
// Deprecate old policies.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0094 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
- id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) {
+ id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083 ||
+ id == cmPolicies::CMP0091))) {
this->IssueMessage(MessageType::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
@@ -4551,3 +4519,22 @@ cmMakefile::MacroPushPop::~MacroPushPop()
{
this->Makefile->PopMacroScope(this->ReportError);
}
+
+cmMakefile::DebugFindPkgRAII::DebugFindPkgRAII(cmMakefile* mf,
+ std::string const& pkg)
+ : Makefile(mf)
+ , OldValue(this->Makefile->DebugFindPkg)
+{
+ this->Makefile->DebugFindPkg =
+ this->Makefile->GetCMakeInstance()->GetDebugFindPkgOutput(pkg);
+}
+
+cmMakefile::DebugFindPkgRAII::~DebugFindPkgRAII()
+{
+ this->Makefile->DebugFindPkg = this->OldValue;
+}
+
+bool cmMakefile::GetDebugFindPkgMode() const
+{
+ return this->DebugFindPkg;
+}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 671cdab..f425697 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -24,6 +24,7 @@
#include "cm_sys_stat.h"
#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandTypes.h"
#include "cmListFileCache.h"
#include "cmMessageType.h"
@@ -50,7 +51,6 @@ class cmExportBuildFileGenerator;
class cmFunctionBlocker;
class cmGeneratorExpressionEvaluationFile;
class cmGlobalGenerator;
-class cmImplicitDependsList;
class cmInstallGenerator;
class cmLocalGenerator;
class cmMessenger;
@@ -140,13 +140,47 @@ public:
bool EnforceUniqueName(std::string const& name, std::string& msg,
bool isCustom = false) const;
- using GeneratorAction =
- std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>;
+ class GeneratorAction
+ {
+ using ActionT =
+ std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>;
+ using CCActionT =
+ std::function<void(cmLocalGenerator&, const cmListFileBacktrace&,
+ std::unique_ptr<cmCustomCommand> cc)>;
+
+ public:
+ GeneratorAction(ActionT&& action)
+ : Action(std::move(action))
+ {
+ }
+
+ GeneratorAction(std::unique_ptr<cmCustomCommand> tcc, CCActionT&& action)
+ : CCAction(std::move(action))
+ , cc(std::move(tcc))
+ {
+ }
+
+ void operator()(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt);
+
+ private:
+ ActionT Action;
+
+ // FIXME: Use std::variant
+ CCActionT CCAction;
+ std::unique_ptr<cmCustomCommand> cc;
+ };
/**
* Register an action that is executed during Generate
*/
- void AddGeneratorAction(GeneratorAction action);
+ void AddGeneratorAction(GeneratorAction&& action);
+
+ /// Helper to insert the constructor GeneratorAction(args...)
+ template <class... Args>
+ void AddGeneratorAction(Args&&... args)
+ {
+ AddGeneratorAction(GeneratorAction(std::move(args)...));
+ }
/**
* Perform generate actions, Library dependency analysis etc before output of
@@ -165,15 +199,9 @@ public:
* Dispatch adding a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a
* target.
*/
- cmTarget* AddCustomCommandToTarget(
- const std::string& target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir,
- cmPolicies::PolicyStatus cmp0116, bool escapeOldStyle = true,
- bool uses_terminal = false, const std::string& depfile = "",
- const std::string& job_pool = "", bool command_expand_lists = false,
- bool stdPipesUTF8 = false);
+ cmTarget* AddCustomCommandToTarget(const std::string& target,
+ cmCustomCommandType type,
+ std::unique_ptr<cmCustomCommand> cc);
/**
* Called for each file with custom command.
@@ -184,33 +212,14 @@ public:
* Dispatch adding a custom command to a source file.
*/
void 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, cmPolicies::PolicyStatus cmp0116,
- const CommandSourceCallback& callback = nullptr, bool replace = false,
- bool escapeOldStyle = true, bool uses_terminal = false,
- bool command_expand_lists = false, const std::string& depfile = "",
- const std::string& job_pool = "", bool stdPipesUTF8 = false);
- void AddCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, cmPolicies::PolicyStatus cmp0116,
- const CommandSourceCallback& callback = nullptr, bool replace = false,
- bool escapeOldStyle = true, bool uses_terminal = false,
- bool command_expand_lists = false, const std::string& depfile = "",
- const std::string& job_pool = "", bool stdPipesUTF8 = false);
+ std::unique_ptr<cmCustomCommand> cc,
+ const CommandSourceCallback& callback = nullptr, bool replace = false);
void AddCustomCommandOldStyle(const std::string& target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const std::string& source,
const cmCustomCommandLines& commandLines,
- const char* comment,
- cmPolicies::PolicyStatus cmp0116);
+ const char* comment);
void AppendCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const cmImplicitDependsList& implicit_depends,
@@ -252,14 +261,9 @@ public:
* Dispatch adding a utility to the build. A utility target is a command
* that is run every time the target is built.
*/
- cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
- const char* workingDir, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmPolicies::PolicyStatus cmp0116,
- bool escapeOldStyle = true, const char* comment = nullptr,
- bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& job_pool = "", bool stdPipesUTF8 = false);
+ cmTarget* AddUtilityCommand(const std::string& utilityName,
+ bool excludeFromAll,
+ std::unique_ptr<cmCustomCommand> cc);
/**
* Add a subdirectory to the build.
@@ -927,6 +931,18 @@ public:
// searches
std::deque<std::vector<std::string>> FindPackageRootPathStack;
+ class DebugFindPkgRAII
+ {
+ cmMakefile* Makefile;
+ bool OldValue;
+
+ public:
+ DebugFindPkgRAII(cmMakefile* mf, std::string const& pkg);
+ ~DebugFindPkgRAII();
+ };
+
+ bool GetDebugFindPkgMode() const;
+
void MaybeWarnCMP0074(std::string const& pkg);
void MaybeWarnUninitialized(std::string const& variable,
const char* sourceFilename) const;
@@ -1100,6 +1116,8 @@ private:
std::vector<BT<GeneratorAction>> GeneratorActions;
bool GeneratorActionsInvoked = false;
+ bool DebugFindPkg = false;
+
bool CheckSystemVars;
bool CheckCMP0000;
std::set<std::string> WarnedCMP0074;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 575fb05..e41ed8c 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -170,9 +170,6 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// Expand the rule variables.
{
- bool useWatcomQuote =
- this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
-
// Set path conversion for link script shells.
this->LocalGenerator->SetLinkScriptShell(useLinkScript);
@@ -181,7 +178,6 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetForResponse(useResponseFileForLibs);
- linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
linkLineComputer->SetRelink(relink);
// Collect up flags to link in needed libraries.
@@ -193,7 +189,7 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// rule.
std::string buildObjs;
this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
- buildObjs, depends, useWatcomQuote);
+ buildObjs, depends, false);
std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
@@ -204,11 +200,9 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir),
cmOutputConverter::SHELL);
- cmOutputConverter::OutputFormat output = (useWatcomQuote)
- ? cmOutputConverter::WATCOMQUOTE
- : cmOutputConverter::SHELL;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput),
+ cmOutputConverter::SHELL);
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ace73a7..66031db 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -308,9 +308,6 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
// 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);
@@ -321,7 +318,6 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetForResponse(useResponseFileForLibs);
- linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
linkLineComputer->SetRelink(relink);
this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
@@ -332,11 +328,7 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
std::string buildObjs;
this->CreateObjectLists(useLinkScript, false, // useArchiveRules
useResponseFileForObjects, buildObjs, depends,
- useWatcomQuote);
-
- cmOutputConverter::OutputFormat output = (useWatcomQuote)
- ? cmOutputConverter::WATCOMQUOTE
- : cmOutputConverter::SHELL;
+ false);
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
@@ -344,7 +336,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
cmOutputConverter::SHELL);
std::string target = this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput), output);
+ this->LocalGenerator->MaybeRelativeToCurBinDir(targetOutput),
+ cmOutputConverter::SHELL);
std::string targetFullPathCompilePDB =
this->ComputeTargetCompilePDB(this->GetConfigName());
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 5f138ba..1c92c7f 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -899,28 +899,31 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Construct the compile rules.
{
- std::vector<std::string> compileCommands;
+ std::string cudaCompileMode;
if (lang == "CUDA") {
- std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
- } else if (this->GeneratorTarget->GetPropertyAsBool(
- "CUDA_PTX_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
+ const std::string& rdcFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
+ }
+ if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
+ const std::string& ptxFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
} else {
- cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
+ const std::string& wholeFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
}
- const std::string& compileRule =
- this->Makefile->GetRequiredDefinition(cmdVar);
- cmExpandList(compileRule, compileCommands);
- } else {
- const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT";
- const std::string& compileRule =
- this->Makefile->GetRequiredDefinition(cmdVar);
- cmExpandList(compileRule, compileCommands);
+ vars.CudaCompileMode = cudaCompileMode.c_str();
}
+ std::vector<std::string> compileCommands;
+ const std::string& compileRule = this->Makefile->GetRequiredDefinition(
+ "CMAKE_" + lang + "_COMPILE_OBJECT");
+ cmExpandList(compileRule, compileCommands);
+
if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") &&
lang_can_export_cmds && compileCommands.size() == 1) {
std::string compileCommand = compileCommands[0];
@@ -1529,9 +1532,9 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
return;
}
+ cmLocalUnixMakefileGenerator3* localGen{ this->LocalGenerator };
std::vector<std::string> architectures = cmExpandedList(architecturesStr);
- std::string const& relPath =
- this->LocalGenerator->GetHomeRelativeOutputPath();
+ std::string const& relPath = localGen->GetHomeRelativeOutputPath();
// Ensure there are no duplicates.
const std::vector<std::string> linkDeps = [&]() -> std::vector<std::string> {
@@ -1551,12 +1554,12 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
const std::string objectDir = this->GeneratorTarget->ObjectDirectory;
const std::string relObjectDir =
- this->LocalGenerator->MaybeRelativeToCurBinDir(objectDir);
+ localGen->MaybeRelativeToCurBinDir(objectDir);
// Construct a list of files associated with this executable that
// may need to be cleaned.
std::vector<std::string> cleanFiles;
- cleanFiles.push_back(this->LocalGenerator->MaybeRelativeToCurBinDir(output));
+ cleanFiles.push_back(localGen->MaybeRelativeToCurBinDir(output));
std::string profiles;
std::vector<std::string> fatbinaryDepends;
@@ -1593,8 +1596,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
" -arch=sm_", architecture, registerFileCmd, " -o=$@ ",
cmJoin(linkDeps, " "));
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, cubin,
- linkDeps, { command }, false);
+ localGen->WriteMakeRule(*this->BuildFileStream, nullptr, cubin, linkDeps,
+ { command }, false);
}
// Combine all architectures into a single fatbinary.
@@ -1608,9 +1611,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
const std::string fatbinaryOutputRel =
cmStrCat(relPath, relObjectDir, "cmake_cuda_fatbin.h");
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
- fatbinaryOutputRel, fatbinaryDepends,
- { fatbinaryCommand }, false);
+ localGen->WriteMakeRule(*this->BuildFileStream, nullptr, fatbinaryOutputRel,
+ fatbinaryDepends, { fatbinaryCommand }, false);
// Compile the stub that registers the kernels and contains the
// fatbinaries.
@@ -1624,18 +1626,21 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
vars.Fatbinary = fatbinaryOutput.c_str();
vars.RegisterFile = registerFile.c_str();
+ std::string linkFlags;
+ this->GetDeviceLinkFlags(linkFlags, "CUDA");
+ vars.LinkFlags = linkFlags.c_str();
+
std::string flags = this->GetFlags("CUDA", this->GetConfigName());
vars.Flags = flags.c_str();
std::string compileCmd = this->GetLinkRule("CMAKE_CUDA_DEVICE_LINK_COMPILE");
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
- this->LocalGenerator->CreateRulePlaceholderExpander());
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
- compileCmd, vars);
+ localGen->CreateRulePlaceholderExpander());
+ rulePlaceholderExpander->ExpandRuleVariables(localGen, compileCmd, vars);
commands.emplace_back(compileCmd);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, output,
- { fatbinaryOutputRel }, commands, false);
+ localGen->WriteMakeRule(*this->BuildFileStream, nullptr, output,
+ { fatbinaryOutputRel }, commands, false);
// Clean all the possible executable names and symlinks.
this->CleanFiles.insert(cleanFiles.begin(), cleanFiles.end());
@@ -2186,7 +2191,7 @@ void cmMakefileTargetGenerator::CreateObjectLists(
for (unsigned int i = 0; i < object_strings.size(); ++i) {
// Number the response files.
char rsp[32];
- sprintf(rsp, "objects%u.rsp", i + 1);
+ snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1);
// Create this response file.
std::string objects_rsp =
diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx
index 56221bf..df9ebcf 100644
--- a/Source/cmMathCommand.cxx
+++ b/Source/cmMathCommand.cxx
@@ -107,7 +107,7 @@ bool HandleExprCommand(std::vector<std::string> const& args,
fmt = "%" KWIML_INT_PRId64;
break;
}
- sprintf(buffer, fmt, helper.GetResult());
+ snprintf(buffer, sizeof(buffer), fmt, helper.GetResult());
std::string const& w = helper.GetWarning();
if (!w.empty()) {
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index 1cb638a..6dd192e 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -12,6 +12,7 @@
#endif
#include <sstream>
+#include <utility>
#include "cmsys/Terminal.h"
@@ -102,7 +103,7 @@ static int getMessageColor(MessageType t)
}
}
-void printMessageText(std::ostream& msg, std::string const& text)
+static void printMessageText(std::ostream& msg, std::string const& text)
{
msg << ":\n";
cmDocumentationFormatter formatter;
@@ -110,7 +111,7 @@ void printMessageText(std::ostream& msg, std::string const& text)
formatter.PrintFormatted(msg, text.c_str());
}
-void displayMessage(MessageType t, std::ostringstream& msg)
+static void displayMessage(MessageType t, std::ostringstream& msg)
{
// Add a note about warning suppression.
if (t == MessageType::AUTHOR_WARNING) {
@@ -151,23 +152,55 @@ void displayMessage(MessageType t, std::ostringstream& msg)
}
}
+namespace {
+void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
+ cm::optional<std::string> const& topSource)
+{
+ // The call stack exists only if we have at least two calls on top
+ // of the bottom.
+ if (bt.Empty()) {
+ return;
+ }
+ bt = bt.Pop();
+ if (bt.Empty()) {
+ return;
+ }
+
+ bool first = true;
+ for (; !bt.Empty(); bt = bt.Pop()) {
+ cmListFileContext lfc = bt.Top();
+ if (lfc.Name.empty() &&
+ lfc.Line != cmListFileContext::DeferPlaceholderLine) {
+ // Skip this whole-file scope. When we get here we already will
+ // have printed a more-specific context within the file.
+ continue;
+ }
+ if (first) {
+ first = false;
+ out << "Call Stack (most recent call first):\n";
+ }
+ if (topSource) {
+ lfc.FilePath = cmSystemTools::RelativeIfUnder(*topSource, lfc.FilePath);
+ }
+ out << " " << lfc << "\n";
+ }
+}
+}
+
void cmMessenger::IssueMessage(MessageType t, const std::string& text,
const cmListFileBacktrace& backtrace) const
{
bool force = false;
- if (!force) {
- // override the message type, if needed, for warnings and errors
- MessageType override = this->ConvertMessageType(t);
- if (override != t) {
- t = override;
- force = true;
- }
+ // override the message type, if needed, for warnings and errors
+ MessageType override = this->ConvertMessageType(t);
+ if (override != t) {
+ t = override;
+ force = true;
}
- if (!force && !this->IsMessageTypeVisible(t)) {
- return;
+ if (force || this->IsMessageTypeVisible(t)) {
+ this->DisplayMessage(t, text, backtrace);
}
- this->DisplayMessage(t, text, backtrace);
}
void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
@@ -179,12 +212,32 @@ void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
}
// Add the immediate context.
- backtrace.PrintTitle(msg);
+ this->PrintBacktraceTitle(msg, backtrace);
printMessageText(msg, text);
// Add the rest of the context.
- backtrace.PrintCallStack(msg);
+ PrintCallStack(msg, backtrace, this->TopSource);
displayMessage(t, msg);
}
+
+void cmMessenger::PrintBacktraceTitle(std::ostream& out,
+ cmListFileBacktrace const& bt) const
+{
+ // The title exists only if we have a call on top of the bottom.
+ if (bt.Empty()) {
+ return;
+ }
+ cmListFileContext lfc = bt.Top();
+ if (this->TopSource) {
+ lfc.FilePath =
+ cmSystemTools::RelativeIfUnder(*this->TopSource, lfc.FilePath);
+ }
+ out << (lfc.Line ? " at " : " in ") << lfc;
+}
+
+void cmMessenger::SetTopSource(cm::optional<std::string> topSource)
+{
+ this->TopSource = std::move(topSource);
+}
diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h
index b6f5712..451add0 100644
--- a/Source/cmMessenger.h
+++ b/Source/cmMessenger.h
@@ -4,8 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <iosfwd>
#include <string>
+#include <cm/optional>
+
#include "cmListFileCache.h"
#include "cmMessageType.h"
@@ -19,6 +22,8 @@ public:
void DisplayMessage(MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace) const;
+ void SetTopSource(cm::optional<std::string> topSource);
+
void SetSuppressDevWarnings(bool suppress)
{
this->SuppressDevWarnings = suppress;
@@ -47,10 +52,16 @@ public:
return this->DeprecatedWarningsAsErrors;
}
+ // Print the top of a backtrace.
+ void PrintBacktraceTitle(std::ostream& out,
+ cmListFileBacktrace const& bt) const;
+
private:
bool IsMessageTypeVisible(MessageType t) const;
MessageType ConvertMessageType(MessageType t) const;
+ cm::optional<std::string> TopSource;
+
bool SuppressDevWarnings = false;
bool SuppressDeprecatedWarnings = false;
bool DevWarningsAsErrors = false;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 517d529..1c5bac8 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -326,6 +326,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
vars.Object = "$out";
vars.Fatbinary = "$FATBIN";
vars.RegisterFile = "$REGISTER";
+ vars.LinkFlags = "$LINK_FLAGS";
std::string flags = this->GetFlags("CUDA", config);
vars.Flags = flags.c_str();
@@ -744,9 +745,10 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements(
return deps;
}();
+ cmGlobalNinjaGenerator* globalGen{ this->GetGlobalGenerator() };
const std::string objectDir =
cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
- this->GetGlobalGenerator()->ConfigDirectory(config));
+ globalGen->ConfigDirectory(config));
const std::string ninjaOutputDir = this->ConvertToNinjaPath(objectDir);
cmNinjaBuild fatbinary(this->LanguageLinkerCudaFatbinaryRule(config));
@@ -777,26 +779,37 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatements(
cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
fatbinary.ExplicitDeps.emplace_back(cubin);
- this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), dlink);
+ globalGen->WriteBuild(this->GetCommonFileStream(), dlink);
}
// Combine all architectures into a single fatbinary.
fatbinary.Outputs = { cmStrCat(ninjaOutputDir, "/cmake_cuda_fatbin.h") };
- this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(),
- fatbinary);
+ globalGen->WriteBuild(this->GetCommonFileStream(), fatbinary);
// Compile the stub that registers the kernels and contains the fatbinaries.
+ cmLocalNinjaGenerator* localGen{ this->GetLocalGenerator() };
cmNinjaBuild dcompile(this->LanguageLinkerCudaDeviceCompileRule(config));
dcompile.Outputs = { output };
dcompile.ExplicitDeps = { cmStrCat(ninjaOutputDir, "/cmake_cuda_fatbin.h") };
- dcompile.Variables["FATBIN"] =
- this->GetLocalGenerator()->ConvertToOutputFormat(
- cmStrCat(objectDir, "/cmake_cuda_fatbin.h"), cmOutputConverter::SHELL);
- dcompile.Variables["REGISTER"] =
- this->GetLocalGenerator()->ConvertToOutputFormat(
- cmStrCat(objectDir, "/cmake_cuda_register.h"), cmOutputConverter::SHELL);
- this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(),
- dcompile);
+ dcompile.Variables["FATBIN"] = localGen->ConvertToOutputFormat(
+ cmStrCat(objectDir, "/cmake_cuda_fatbin.h"), cmOutputConverter::SHELL);
+ dcompile.Variables["REGISTER"] = localGen->ConvertToOutputFormat(
+ cmStrCat(objectDir, "/cmake_cuda_register.h"), cmOutputConverter::SHELL);
+
+ cmNinjaLinkLineDeviceComputer linkLineComputer(
+ localGen, localGen->GetStateSnapshot().GetDirectory(), globalGen);
+ linkLineComputer.SetUseNinjaMulti(globalGen->IsMultiConfig());
+
+ // Link libraries and paths are only used during the final executable/library
+ // link.
+ std::string frameworkPath;
+ std::string linkPath;
+ std::string linkLibs;
+ localGen->GetDeviceLinkFlags(linkLineComputer, config, linkLibs,
+ dcompile.Variables["LINK_FLAGS"], frameworkPath,
+ linkPath, this->GetGeneratorTarget());
+
+ globalGen->WriteBuild(this->GetCommonFileStream(), dcompile);
}
void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
@@ -850,24 +863,19 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
std::string createRule =
genTarget->GetCreateRuleVariable(this->TargetLinkLanguage(config), config);
- const bool useWatcomQuote =
- this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE");
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
vars["TARGET_FILE"] =
localGen.ConvertToOutputFormat(output, cmOutputConverter::SHELL);
- std::unique_ptr<cmLinkLineComputer> linkLineComputer(
- new cmNinjaLinkLineDeviceComputer(
- this->GetLocalGenerator(),
- this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(),
- globalGen));
- linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
- linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig());
+ cmNinjaLinkLineDeviceComputer linkLineComputer(
+ this->GetLocalGenerator(),
+ this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(), globalGen);
+ linkLineComputer.SetUseNinjaMulti(globalGen->IsMultiConfig());
- localGen.GetDeviceLinkFlags(linkLineComputer.get(), config,
- vars["LINK_LIBRARIES"], vars["LINK_FLAGS"],
- frameworkPath, linkPath, genTarget);
+ localGen.GetDeviceLinkFlags(linkLineComputer, config, vars["LINK_LIBRARIES"],
+ vars["LINK_FLAGS"], frameworkPath, linkPath,
+ genTarget);
this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 57657b1..dd7d244 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -216,7 +216,8 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add Fortran format flags.
if (language == "Fortran") {
this->AppendFortranFormatFlags(flags, *source);
- this->AppendFortranPreprocessFlags(flags, *source);
+ this->AppendFortranPreprocessFlags(flags, *source,
+ PreprocessFlagsRequired::NO);
}
// Add source file specific flags.
@@ -263,10 +264,7 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
language, config);
// Add include directory flags.
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language, config, false,
- // full include paths for RC needed by cmcldeps
- language == "RC" ? cmLocalGenerator::IncludePathStyle::Absolute
- : cmLocalGenerator::IncludePathStyle::Default);
+ includes, this->GeneratorTarget, language, config, false);
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
}
@@ -325,8 +323,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
}
std::string includesString = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, language, config, false,
- cmLocalGenerator::IncludePathStyle::Absolute);
+ includes, this->GeneratorTarget, language, config, false);
this->LocalGenerator->AppendFlags(includesString,
this->GetIncludes(language, config));
@@ -605,6 +602,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";
vars.ObjectDir = "$OBJECT_DIR";
vars.ObjectFileDir = "$OBJECT_FILE_DIR";
+ vars.CudaCompileMode = "$CUDA_COMPILE_MODE";
vars.ISPCHeader = "$ISPC_HEADER_FILE";
cmMakefile* mf = this->GetMakefile();
@@ -815,27 +813,32 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
vars.Flags = flags.c_str();
vars.DependencyFile = rule.DepFile.c_str();
- // Rule for compiling object file.
- std::vector<std::string> compileCmds;
+ std::string cudaCompileMode;
if (lang == "CUDA") {
- std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
- } else if (this->GeneratorTarget->GetPropertyAsBool(
- "CUDA_PTX_COMPILATION")) {
- cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
+ const std::string& rdcFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_RDC_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, rdcFlag, " ");
+ }
+ if (this->GeneratorTarget->GetPropertyAsBool("CUDA_PTX_COMPILATION")) {
+ const std::string& ptxFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_PTX_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, ptxFlag);
} else {
- cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
+ const std::string& wholeFlag =
+ this->Makefile->GetRequiredDefinition("_CMAKE_CUDA_WHOLE_FLAG");
+ cudaCompileMode = cmStrCat(cudaCompileMode, wholeFlag);
}
- const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
- cmExpandList(compileCmd, compileCmds);
- } else {
- const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT");
- const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
- cmExpandList(compileCmd, compileCmds);
+ vars.CudaCompileMode = cudaCompileMode.c_str();
}
+ // Rule for compiling object file.
+ std::vector<std::string> compileCmds;
+ const std::string cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT");
+ const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileCmd, compileCmds);
+
// See if we need to use a compiler launcher like ccache or distcc
std::string compilerLauncher;
if (!compileCmds.empty() &&
@@ -1407,8 +1410,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmSystemTools::GetParentDirectory(source->GetFullPath()));
std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
- sourceDirectory, this->GeneratorTarget, language, config, false,
- cmLocalGenerator::IncludePathStyle::Default);
+ sourceDirectory, this->GeneratorTarget, language, config, false);
vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]);
}
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 2b785e1..b143170 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -8,6 +8,11 @@
#include <set>
#include <vector>
+#ifdef _WIN32
+# include <unordered_map>
+# include <utility>
+#endif
+
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStringAlgorithms.h"
@@ -117,17 +122,34 @@ std::string cmOutputConverter::MaybeRelativeToCurBinDir(
std::string cmOutputConverter::ConvertToOutputForExisting(
const std::string& remote, OutputFormat format) const
{
+#ifdef _WIN32
+ // Cache the Short Paths since we only convert the same few paths anyway and
+ // calling `GetShortPathNameW` is really expensive.
+ static std::unordered_map<std::string, std::string> shortPathCache{};
+
// 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_first_of(" #") != std::string::npos &&
cmSystemTools::FileExists(remote)) {
- std::string tmp;
- if (cmSystemTools::GetShortPath(remote, tmp)) {
- return this->ConvertToOutputFormat(tmp, format);
- }
+
+ std::string shortPath = [&]() {
+ auto cachedShortPathIt = shortPathCache.find(remote);
+
+ if (cachedShortPathIt != shortPathCache.end()) {
+ return cachedShortPathIt->second;
+ }
+
+ std::string tmp{};
+ cmSystemTools::GetShortPath(remote, tmp);
+ shortPathCache[remote] = tmp;
+ return tmp;
+ }();
+
+ return this->ConvertToOutputFormat(shortPath, format);
}
+#endif
// Otherwise, perform standard conversion.
return this->ConvertToOutputFormat(remote, format);
@@ -143,7 +165,7 @@ std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE,
output == NINJAMULTI);
} else if (output == RESPONSE) {
- result = this->EscapeForShell(result, false, false, false);
+ result = this->EscapeForShell(result, false, false, false, false, true);
}
return result;
}
@@ -175,9 +197,11 @@ static bool cmOutputConverterIsShellOperator(cm::string_view str)
return (shellOperators.count(str) != 0);
}
-std::string cmOutputConverter::EscapeForShell(
- cm::string_view str, bool makeVars, bool forEcho, bool useWatcomQuote,
- bool unescapeNinjaConfiguration) const
+std::string cmOutputConverter::EscapeForShell(cm::string_view str,
+ bool makeVars, bool forEcho,
+ bool useWatcomQuote,
+ bool unescapeNinjaConfiguration,
+ bool forResponse) const
{
// Do not escape shell operators.
if (cmOutputConverterIsShellOperator(str)) {
@@ -203,6 +227,9 @@ std::string cmOutputConverter::EscapeForShell(
if (useWatcomQuote) {
flags |= Shell_Flag_WatcomQuote;
}
+ if (forResponse) {
+ flags |= Shell_Flag_IsResponse;
+ }
if (this->GetState()->UseWatcomWMake()) {
flags |= Shell_Flag_WatcomWMake;
}
@@ -219,10 +246,11 @@ std::string cmOutputConverter::EscapeForShell(
return Shell_GetArgument(str, flags);
}
-std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
+std::string cmOutputConverter::EscapeForCMake(cm::string_view str,
+ WrapQuotes wrapQuotes)
{
// Always double-quote the argument to take care of most escapes.
- std::string result = "\"";
+ std::string result = (wrapQuotes == WrapQuotes::Wrap) ? "\"" : "";
for (const char c : str) {
if (c == '"') {
// Escape the double quote to avoid ending the argument.
@@ -238,7 +266,9 @@ std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
result += c;
}
}
- result += "\"";
+ if (wrapQuotes == WrapQuotes::Wrap) {
+ result += "\"";
+ }
return result;
}
@@ -357,6 +387,13 @@ bool cmOutputConverter::Shell_CharNeedsQuotes(char c, int flags)
return true;
}
+ /* Quote hyphens in response files */
+ if (flags & Shell_Flag_IsResponse) {
+ if (c == '-') {
+ return true;
+ }
+ }
+
if (flags & Shell_Flag_IsUnix) {
/* On UNIX several special characters need quotes to preserve them. */
if (Shell_CharNeedsQuotesOnUnix(c)) {
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 865df71..335442d 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -88,13 +88,22 @@ public:
Shell_Flag_IsUnix = (1 << 8),
Shell_Flag_UnescapeNinjaConfiguration = (1 << 9),
+
+ Shell_Flag_IsResponse = (1 << 10)
};
std::string EscapeForShell(cm::string_view str, bool makeVars = false,
bool forEcho = false, bool useWatcomQuote = false,
- bool unescapeNinjaConfiguration = false) const;
+ bool unescapeNinjaConfiguration = false,
+ bool forResponse = false) const;
- static std::string EscapeForCMake(cm::string_view str);
+ enum class WrapQuotes
+ {
+ Wrap,
+ NoWrap,
+ };
+ static std::string EscapeForCMake(cm::string_view str,
+ WrapQuotes wrapQuotes = WrapQuotes::Wrap);
/** Compute an escaped version of the given argument for use in a
windows shell. */
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 23000fa..e31de1c 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -103,7 +103,7 @@ static bool isPolicyNewerThan(cmPolicies::PolicyID id, unsigned int majorV,
return false;
}
-const char* idToShortDescription(cmPolicies::PolicyID id)
+static const char* idToShortDescription(cmPolicies::PolicyID id)
{
switch (id) {
#define POLICY_CASE(ID, SHORT_DESCRIPTION) \
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index ce04117..99e2eb6 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -385,7 +385,10 @@ class cmMakefile;
0, cmPolicies::WARN) \
SELECT(POLICY, CMP0128, \
"Selection of language standard and extension flags improved.", 3, \
- 22, 0, cmPolicies::WARN)
+ 22, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0129, \
+ "Compiler id for MCST LCC compilers is now LCC, not GNU.", 3, 23, 0, \
+ cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 20fcdbe..04d99c9 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -235,14 +235,15 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) {
- char vb[MAX_VERSION_COMPONENTS]
- [std::numeric_limits<unsigned>::digits10 + 2];
+ constexpr size_t maxIntLength =
+ std::numeric_limits<unsigned>::digits10 + 2;
+ char vb[MAX_VERSION_COMPONENTS][maxIntLength];
unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 };
const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1],
&v[2], &v[3]);
for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) {
if (int(i) < vc) {
- std::sprintf(vb[i], "%u", v[i]);
+ std::snprintf(vb[i], maxIntLength, "%u", v[i]);
version_string += &"."[std::size_t(i == 0)];
version_string += vb[i];
version_components[i] = vb[i];
diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx
index 1796bb8..22723b9 100644
--- a/Source/cmPropertyDefinition.cxx
+++ b/Source/cmPropertyDefinition.cxx
@@ -6,31 +6,34 @@
cmPropertyDefinition::cmPropertyDefinition(std::string shortDescription,
std::string fullDescription,
- bool chained)
+ bool chained,
+ std::string initializeFromVariable)
: ShortDescription(std::move(shortDescription))
, FullDescription(std::move(fullDescription))
, Chained(chained)
+ , InitializeFromVariable(std::move(initializeFromVariable))
{
}
void cmPropertyDefinitionMap::DefineProperty(
const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription, const std::string& FullDescription,
- bool chain)
+ bool chain, const std::string& initializeFromVariable)
{
- auto it = this->Map_.find(key_type(name, scope));
+ auto it = this->Map_.find(KeyType(name, scope));
if (it == this->Map_.end()) {
// try_emplace() since C++17
- this->Map_.emplace(
- std::piecewise_construct, std::forward_as_tuple(name, scope),
- std::forward_as_tuple(ShortDescription, FullDescription, chain));
+ this->Map_.emplace(std::piecewise_construct,
+ std::forward_as_tuple(name, scope),
+ std::forward_as_tuple(ShortDescription, FullDescription,
+ chain, initializeFromVariable));
}
}
cmPropertyDefinition const* cmPropertyDefinitionMap::GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const
{
- auto it = this->Map_.find(key_type(name, scope));
+ auto it = this->Map_.find(KeyType(name, scope));
if (it != this->Map_.end()) {
return &it->second;
}
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index fca936e..9dd2cfe 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -22,7 +22,8 @@ class cmPropertyDefinition
public:
/// Constructor
cmPropertyDefinition(std::string shortDescription,
- std::string fullDescription, bool chained);
+ std::string fullDescription, bool chained,
+ std::string initializeFromVariable);
/// Is the property chained?
bool IsChained() const { return this->Chained; }
@@ -39,10 +40,17 @@ public:
return this->FullDescription;
}
+ /// Get the variable the property is initialized from
+ const std::string& GetInitializeFromVariable() const
+ {
+ return this->InitializeFromVariable;
+ }
+
private:
std::string ShortDescription;
std::string FullDescription;
bool Chained;
+ std::string InitializeFromVariable;
};
/** \class cmPropertyDefinitionMap
@@ -54,13 +62,19 @@ public:
// define the property
void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chain);
+ const std::string& FullDescription, bool chain,
+ const std::string& initializeFromVariable);
// get the property definition if present, otherwise nullptr
cmPropertyDefinition const* GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const;
+ using KeyType = std::pair<std::string, cmProperty::ScopeType>;
+ const std::map<KeyType, cmPropertyDefinition>& GetMap() const
+ {
+ return this->Map_;
+ }
+
private:
- using key_type = std::pair<std::string, cmProperty::ScopeType>;
- std::map<key_type, cmPropertyDefinition> Map_;
+ std::map<KeyType, cmPropertyDefinition> Map_;
};
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index ca0b259..58cf514 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -2,10 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQTWrapCPPCommand.h"
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -71,11 +75,12 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
depends.push_back(moc_exe);
depends.push_back(hname);
- std::string no_main_dependency;
- const char* no_working_dir = nullptr;
- mf.AddCustomCommandToOutput(
- newName, depends, no_main_dependency, commandLines, "Qt Wrapped File",
- no_working_dir, mf.GetPolicyStatus(cmPolicies::CMP0116));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(newName);
+ cc->SetDepends(depends);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment("Qt Wrapped File");
+ mf.AddCustomCommandToOutput(std::move(cc));
}
}
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index f98f0b3..8b2a42c 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -2,10 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQTWrapUICommand.h"
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -84,23 +88,26 @@ bool cmQTWrapUICommand(std::vector<std::string> const& args,
std::vector<std::string> depends;
depends.push_back(uiName);
- std::string no_main_dependency;
- const char* no_comment = nullptr;
- const char* no_working_dir = nullptr;
- mf.AddCustomCommandToOutput(hName, depends, no_main_dependency,
- hCommandLines, no_comment, no_working_dir,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(hName);
+ cc->SetDepends(depends);
+ cc->SetCommandLines(hCommandLines);
+ mf.AddCustomCommandToOutput(std::move(cc));
depends.push_back(hName);
- mf.AddCustomCommandToOutput(cxxName, depends, no_main_dependency,
- cxxCommandLines, no_comment, no_working_dir,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(cxxName);
+ cc->SetDepends(depends);
+ cc->SetCommandLines(cxxCommandLines);
+ mf.AddCustomCommandToOutput(std::move(cc));
depends.clear();
depends.push_back(hName);
- mf.AddCustomCommandToOutput(mocName, depends, no_main_dependency,
- mocCommandLines, no_comment, no_working_dir,
- mf.GetPolicyStatus(cmPolicies::CMP0116));
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(mocName);
+ cc->SetDepends(depends);
+ cc->SetCommandLines(mocCommandLines);
+ mf.AddCustomCommandToOutput(std::move(cc));
}
}
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 9584e5c..0a394b5 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -22,10 +22,10 @@
/// @brief Merges newOpts into baseOpts
/// @arg valueOpts list of options that accept a value
-void MergeOptions(std::vector<std::string>& baseOpts,
- std::vector<std::string> const& newOpts,
- std::initializer_list<cm::string_view> valueOpts,
- bool isQt5OrLater)
+static void MergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ std::initializer_list<cm::string_view> valueOpts,
+ bool isQt5OrLater)
{
if (newOpts.empty()) {
return;
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index f9e889a..b7ea7d6 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -7,7 +7,7 @@
#include <cm/memory>
-#include "cmCustomCommandLines.h"
+#include "cmCustomCommand.h"
#include "cmDuration.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
@@ -171,13 +171,12 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
cmMakefile* makefile = localGen->GetMakefile();
// Create utility target
- std::vector<std::string> no_byproducts;
- std::vector<std::string> no_depends;
- cmCustomCommandLines no_commands;
- const cmPolicies::PolicyStatus cmp0116_new = cmPolicies::NEW;
- cmTarget* target = localGen->AddUtilityCommand(
- name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts,
- no_depends, no_commands, cmp0116_new, false, comment.c_str());
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetWorkingDirectory(makefile->GetHomeOutputDirectory().c_str());
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetComment(comment.c_str());
+ cmTarget* target = localGen->AddUtilityCommand(name, true, std::move(cc));
localGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(target, localGen));
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index c49cafe..a01e6ae 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -636,12 +636,12 @@ bool cmQtAutoGenInitializer::InitMoc()
auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
std::set<std::string> defines;
this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
-#ifdef _WIN32
- if (this->Moc.PredefsCmd.empty()) {
+ if (this->Moc.PredefsCmd.empty() &&
+ this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") ==
+ "Windows") {
// Add WIN32 definition if we don't have a moc_predefs.h
defines.insert("WIN32");
}
-#endif
return defines;
};
@@ -1230,15 +1230,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// Add a rule file to cause the target to build if a dependency has
// changed, which will trigger the pre-build command to run autogen
- std::string no_main_dependency;
- cmCustomCommandLines no_command_lines;
- this->LocalGen->AddCustomCommandToOutput(
- timestampFileGenex, uicDependencies, no_main_dependency,
- no_command_lines, /*comment=*/"", this->Dir.Work.c_str(),
- /*cmp0116=*/cmPolicies::NEW, /*replace=*/false,
- /*escapeOldStyle=*/false, /*uses_terminal=*/false,
- /*command_expand_lists=*/false, /*depfile=*/"", /*job_pool=*/"",
- stdPipesUTF8);
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(timestampFileGenex);
+ cc->SetDepends(uicDependencies);
+ cc->SetComment("");
+ cc->SetWorkingDirectory(this->Dir.Work.c_str());
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetStdPipesUTF8(stdPipesUTF8);
+ this->LocalGen->AddCustomCommandToOutput(std::move(cc));
}
// Add the pre-build command directly to bypass the OBJECT_LIBRARY
@@ -1246,11 +1246,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
//
// PRE_BUILD does not support file dependencies!
- const std::vector<std::string> no_output;
- const std::vector<std::string> no_deps;
- cmCustomCommand cc(no_output, autogenByproducts, no_deps, commandLines,
- this->Makefile->GetBacktrace(), autogenComment.c_str(),
- this->Dir.Work.c_str(), stdPipesUTF8);
+ cmCustomCommand cc;
+ cc.SetByproducts(autogenByproducts);
+ cc.SetCommandLines(commandLines);
+ cc.SetComment(autogenComment.c_str());
+ cc.SetBacktrace(this->Makefile->GetBacktrace());
+ cc.SetWorkingDirectory(this->Dir.Work.c_str());
+ cc.SetStdPipesUTF8(stdPipesUTF8);
cc.SetEscapeOldStyle(false);
cc.SetEscapeAllowMakeVars(true);
this->GenTarget->Target->AddPreBuildCommand(std::move(cc));
@@ -1321,11 +1323,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
dependencies.push_back(depname);
}
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetWorkingDirectory(this->Dir.Work.c_str());
+ cc->SetByproducts(timestampTargetProvides);
+ cc->SetDepends(dependencies);
+ cc->SetCommandLines(timestampTargetCommandLines);
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
cmTarget* timestampTarget = this->LocalGen->AddUtilityCommand(
- timestampTargetName, true, this->Dir.Work.c_str(),
- /*byproducts=*/timestampTargetProvides,
- /*depends=*/dependencies, timestampTargetCommandLines, cmPolicies::NEW,
- false, nullptr);
+ timestampTargetName, true, std::move(cc));
this->LocalGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));
@@ -1354,16 +1360,18 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
{ cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));
this->AddGeneratedSource(outputFile, this->Moc);
- const std::string no_main_dependency;
- this->LocalGen->AddCustomCommandToOutput(
- { outputFile }, timestampByproducts, dependencies, no_main_dependency,
- /*implicit_depends=*/{}, commandLines, autogenComment.c_str(),
- this->Dir.Work.c_str(),
- /*cmp0116=*/cmPolicies::NEW, /*replace=*/false,
- /*escapeOldStyle=*/false,
- /*uses_terminal=*/false,
- /*command_expand_lists=*/false, this->AutogenTarget.DepFile, "",
- stdPipesUTF8);
+ cc = cm::make_unique<cmCustomCommand>();
+ cc->SetOutputs(outputFile);
+ cc->SetByproducts(timestampByproducts);
+ cc->SetDepends(dependencies);
+ cc->SetCommandLines(commandLines);
+ cc->SetComment(autogenComment.c_str());
+ cc->SetWorkingDirectory(this->Dir.Work.c_str());
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetDepfile(this->AutogenTarget.DepFile);
+ cc->SetStdPipesUTF8(stdPipesUTF8);
+ this->LocalGen->AddCustomCommandToOutput(std::move(cc));
// Alter variables for the autogen target which now merely wraps the
// custom command
@@ -1374,11 +1382,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
// Create autogen target
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetWorkingDirectory(this->Dir.Work.c_str());
+ cc->SetByproducts(autogenByproducts);
+ cc->SetDepends(dependencies);
+ cc->SetCommandLines(commandLines);
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetEscapeOldStyle(false);
+ cc->SetComment(autogenComment.c_str());
cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
- this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
- /*byproducts=*/autogenByproducts,
- /*depends=*/dependencies, commandLines, cmPolicies::NEW, false,
- autogenComment.c_str());
+ this->AutogenTarget.Name, true, std::move(cc));
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));
@@ -1435,7 +1448,6 @@ bool cmQtAutoGenInitializer::InitRccTargets()
ccDepends.push_back(qrc.QrcFile);
ccDepends.push_back(qrc.InfoFile);
- bool stdPipesUTF8 = true;
cmCustomCommandLines commandLines;
if (this->MultiConfig) {
// Build for all configurations
@@ -1453,6 +1465,13 @@ bool cmQtAutoGenInitializer::InitRccTargets()
cmStrCat("Automatic RCC for ",
FileProjectRelativePath(this->Makefile, qrc.QrcFile));
+ auto cc = cm::make_unique<cmCustomCommand>();
+ cc->SetWorkingDirectory(this->Dir.Work.c_str());
+ cc->SetCommandLines(commandLines);
+ cc->SetCMP0116Status(cmPolicies::NEW);
+ cc->SetComment(ccComment.c_str());
+ cc->SetStdPipesUTF8(true);
+
if (qrc.Generated || this->Rcc.GlobalTarget) {
// Create custom rcc target
std::string ccName;
@@ -1462,10 +1481,11 @@ bool cmQtAutoGenInitializer::InitRccTargets()
ccName += cmStrCat('_', qrc.QrcPathChecksum);
}
- cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
- ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
- commandLines, cmPolicies::NEW, false, ccComment.c_str(), false,
- false, "", stdPipesUTF8);
+ cc->SetByproducts(ccOutput);
+ cc->SetDepends(ccDepends);
+ cc->SetEscapeOldStyle(false);
+ cmTarget* autoRccTarget =
+ this->LocalGen->AddUtilityCommand(ccName, true, std::move(cc));
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
@@ -1500,13 +1520,10 @@ bool cmQtAutoGenInitializer::InitRccTargets()
if (!this->Rcc.ExecutableTargetName.empty()) {
ccDepends.push_back(this->Rcc.ExecutableTargetName);
}
- std::string no_main_dependency;
- cmImplicitDependsList no_implicit_depends;
- this->LocalGen->AddCustomCommandToOutput(
- ccOutput, ccByproducts, ccDepends, no_main_dependency,
- no_implicit_depends, commandLines, ccComment.c_str(),
- this->Dir.Work.c_str(), cmPolicies::NEW, false, true, false, false,
- "", "", stdPipesUTF8);
+ cc->SetOutputs(ccOutput);
+ cc->SetByproducts(ccByproducts);
+ cc->SetDepends(ccDepends);
+ this->LocalGen->AddCustomCommandToOutput(std::move(cc));
}
// Reconfigure when .qrc file changes
this->Makefile->AddCMakeDependFile(qrc.QrcFile);
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index 7480aeb..4cee09d 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -85,6 +85,11 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
return replaceValues.ObjectsQuoted;
}
}
+ if (replaceValues.CudaCompileMode) {
+ if (variable == "CUDA_COMPILE_MODE") {
+ return replaceValues.CudaCompileMode;
+ }
+ }
if (replaceValues.AIXExports) {
if (variable == "AIX_EXPORTS") {
return replaceValues.AIXExports;
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index c22e0fa..852954f 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -65,6 +65,7 @@ public:
const char* SwiftOutputFileMap = nullptr;
const char* SwiftSources = nullptr;
const char* ISPCHeader = nullptr;
+ const char* CudaCompileMode = nullptr;
const char* Fatbinary = nullptr;
const char* RegisterFile = nullptr;
const char* Launcher = nullptr;
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index 1bb459c..bfee64c 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -19,23 +19,25 @@ cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
cmSearchPath::~cmSearchPath() = default;
-void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
+void cmSearchPath::ExtractWithout(const std::set<std::string>& ignorePaths,
+ const std::set<std::string>& ignorePrefixes,
std::vector<std::string>& outPaths,
bool clear) const
{
if (clear) {
outPaths.clear();
}
- for (std::string const& path : this->Paths) {
- if (ignore.count(path) == 0) {
- outPaths.push_back(path);
+ for (auto const& path : this->Paths) {
+ if (ignorePaths.count(path.Path) == 0 &&
+ ignorePrefixes.count(path.Prefix) == 0) {
+ outPaths.push_back(path.Path);
}
}
}
void cmSearchPath::AddPath(const std::string& path)
{
- this->AddPathInternal(path);
+ this->AddPathInternal(path, "");
}
void cmSearchPath::AddUserPath(const std::string& path)
@@ -69,7 +71,7 @@ void cmSearchPath::AddUserPath(const std::string& path)
// Process them all from the current directory
for (std::string const& p : outPaths) {
this->AddPathInternal(
- p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
+ p, "", this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
@@ -83,7 +85,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable)
for (std::string const& p : expanded) {
this->AddPathInternal(
- p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
+ p, "", this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
}
@@ -93,7 +95,7 @@ void cmSearchPath::AddEnvPath(const std::string& variable)
std::vector<std::string> expanded;
cmSystemTools::GetPath(expanded, variable.c_str());
for (std::string const& p : expanded) {
- this->AddPathInternal(p);
+ this->AddPathInternal(p, "");
}
}
@@ -132,24 +134,25 @@ void cmSearchPath::AddEnvPrefixPath(const std::string& variable, bool stripBin)
void cmSearchPath::AddSuffixes(const std::vector<std::string>& suffixes)
{
- std::vector<std::string> inPaths;
+ std::vector<PathWithPrefix> inPaths;
inPaths.swap(this->Paths);
this->Paths.reserve(inPaths.size() * (suffixes.size() + 1));
- for (std::string& inPath : inPaths) {
- cmSystemTools::ConvertToUnixSlashes(inPath);
+ for (PathWithPrefix& inPath : inPaths) {
+ cmSystemTools::ConvertToUnixSlashes(inPath.Path);
+ cmSystemTools::ConvertToUnixSlashes(inPath.Prefix);
// 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 = inPath;
+ std::string p = inPath.Path;
if (!p.empty() && p.back() != '/') {
p += "/";
}
// Combine with all the suffixes
for (std::string const& suffix : suffixes) {
- this->Paths.push_back(p + suffix);
+ this->Paths.push_back(PathWithPrefix{ p + suffix, inPath.Prefix });
}
// And now the original w/o any suffix
@@ -178,6 +181,10 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
if (!subdir.empty() && !dir.empty() && dir.back() != '/') {
dir += "/";
}
+ std::string prefix = dir;
+ if (!prefix.empty() && prefix != "/") {
+ prefix.erase(prefix.size() - 1);
+ }
if (subdir == "include" || subdir == "lib") {
cmValue arch =
this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
@@ -185,37 +192,47 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") &&
this->FC->Makefile->IsDefinitionSet(
"CMAKE_PREFIX_LIBRARY_ARCHITECTURE")) {
- this->AddPathInternal(cmStrCat('/', *arch, dir, subdir), base);
+ this->AddPathInternal(cmStrCat('/', *arch, dir, subdir),
+ cmStrCat('/', *arch, prefix), base);
} else {
- this->AddPathInternal(cmStrCat(dir, subdir, '/', *arch), base);
+ this->AddPathInternal(cmStrCat(dir, subdir, '/', *arch), prefix,
+ base);
}
}
}
std::string add = dir + subdir;
if (add != "/") {
- this->AddPathInternal(add, base);
+ this->AddPathInternal(add, prefix, base);
}
if (subdir == "bin") {
- this->AddPathInternal(dir + "sbin", base);
+ this->AddPathInternal(dir + "sbin", prefix, base);
}
if (!subdir.empty() && path != "/") {
- this->AddPathInternal(path, base);
+ this->AddPathInternal(path, prefix, base);
}
}
}
-void cmSearchPath::AddPathInternal(const std::string& path, const char* base)
+void cmSearchPath::AddPathInternal(const std::string& path,
+ const std::string& prefix, const char* base)
{
assert(this->FC != nullptr);
- std::string collapsed = cmSystemTools::CollapseFullPath(path, base);
+ std::string collapsedPath = cmSystemTools::CollapseFullPath(path, base);
- if (collapsed.empty()) {
+ if (collapsedPath.empty()) {
return;
}
+ std::string collapsedPrefix;
+ if (!prefix.empty()) {
+ collapsedPrefix = cmSystemTools::CollapseFullPath(prefix, base);
+ }
+
// Insert the path if has not already been emitted.
- if (this->FC->SearchPathsEmitted.insert(collapsed).second) {
- this->Paths.push_back(std::move(collapsed));
+ PathWithPrefix pathWithPrefix{ std::move(collapsedPath),
+ std::move(collapsedPrefix) };
+ if (this->FC->SearchPathsEmitted.insert(pathWithPrefix).second) {
+ this->Paths.emplace_back(std::move(pathWithPrefix));
}
}
diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h
index c15cb97..4c0cabb 100644
--- a/Source/cmSearchPath.h
+++ b/Source/cmSearchPath.h
@@ -26,10 +26,25 @@ public:
cmSearchPath(cmFindCommon* findCmd = nullptr);
~cmSearchPath();
- const std::vector<std::string>& GetPaths() const { return this->Paths; }
+ cmSearchPath(const cmSearchPath&) = default;
+ cmSearchPath& operator=(const cmSearchPath&) = default;
+
+ struct PathWithPrefix
+ {
+ std::string Path;
+ std::string Prefix;
+
+ bool operator<(const PathWithPrefix& other) const
+ {
+ return this->Path < other.Path ||
+ (this->Path == other.Path && this->Prefix < other.Prefix);
+ }
+ };
+ const std::vector<PathWithPrefix>& GetPaths() const { return this->Paths; }
std::size_t size() const { return this->Paths.size(); }
- void ExtractWithout(const std::set<std::string>& ignore,
+ void ExtractWithout(const std::set<std::string>& ignorePaths,
+ const std::set<std::string>& ignorePrefixes,
std::vector<std::string>& outPaths,
bool clear = false) const;
@@ -44,8 +59,9 @@ public:
const char* base = nullptr);
protected:
- void AddPathInternal(const std::string& path, const char* base = nullptr);
+ void AddPathInternal(const std::string& path, const std::string& prefix,
+ const char* base = nullptr);
cmFindCommon* FC;
- std::vector<std::string> Paths;
+ std::vector<PathWithPrefix> Paths;
};
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index acc2ed2..785f356 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -152,8 +152,12 @@ struct StandardLevelComputer
"dialect \""
<< this->Language << *standardProp << "\" "
<< (ext ? "(with compiler extensions)" : "")
- << ", but CMake "
- "does not know the compile flags to use to enable it.";
+ << ". But the current compiler \""
+ << makefile->GetSafeDefinition("CMAKE_" + this->Language +
+ "_COMPILER_ID")
+ << "\" does not support this, or "
+ "CMake does not know the flags to enable it.";
+
makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
return option_flag;
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index 417f14d..2722528 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -50,6 +50,10 @@
# endif
#endif
+#if defined(__LCC__)
+# pragma diag_suppress 1873 /* comparison between signed and unsigned */
+#endif
+
#if defined(__NVCOMPILER)
# pragma diag_suppress 111 /* statement is unreachable */
# pragma diag_suppress 550 /* variable set but never used */
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index e79949d..f1144e1 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -228,22 +228,22 @@ std::string const& cmState::GetGlobVerifyStamp() const
return this->GlobVerificationManager->GetVerifyStamp();
}
-bool cmState::SaveVerificationScript(const std::string& path)
+bool cmState::SaveVerificationScript(const std::string& path,
+ cmMessenger* messenger)
{
- return this->GlobVerificationManager->SaveVerificationScript(path);
+ return this->GlobVerificationManager->SaveVerificationScript(path,
+ messenger);
}
-void cmState::AddGlobCacheEntry(bool recurse, bool listDirectories,
- bool followSymlinks,
- const std::string& relative,
- const std::string& expression,
- const std::vector<std::string>& files,
- const std::string& variable,
- cmListFileBacktrace const& backtrace)
+void cmState::AddGlobCacheEntry(
+ bool recurse, bool listDirectories, bool followSymlinks,
+ const std::string& relative, const std::string& expression,
+ const std::vector<std::string>& files, const std::string& variable,
+ cmListFileBacktrace const& backtrace, cmMessenger* messenger)
{
this->GlobVerificationManager->AddCacheEntry(
recurse, listDirectories, followSymlinks, relative, expression, files,
- variable, backtrace);
+ variable, backtrace, messenger);
}
void cmState::RemoveCacheEntry(std::string const& key)
@@ -327,10 +327,12 @@ cmStateSnapshot cmState::Reset()
void cmState::DefineProperty(const std::string& name,
cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chained)
+ const std::string& FullDescription, bool chained,
+ const std::string& initializeFromVariable)
{
this->PropertyDefinitions.DefineProperty(name, scope, ShortDescription,
- FullDescription, chained);
+ FullDescription, chained,
+ initializeFromVariable);
}
cmPropertyDefinition const* cmState::GetPropertyDefinition(
diff --git a/Source/cmState.h b/Source/cmState.h
index a1666ca..4f2b7df 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -133,12 +133,18 @@ public:
// Define a property
void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chain = false);
+ const std::string& FullDescription, bool chain = false,
+ const std::string& initializeFromVariable = "");
// get property definition
cmPropertyDefinition const* GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const;
+ const cmPropertyDefinitionMap& GetPropertyDefinitions() const
+ {
+ return this->PropertyDefinitions;
+ }
+
bool IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const;
@@ -238,13 +244,14 @@ private:
bool DoWriteGlobVerifyTarget() const;
std::string const& GetGlobVerifyScript() const;
std::string const& GetGlobVerifyStamp() const;
- bool SaveVerificationScript(const std::string& path);
+ bool SaveVerificationScript(const std::string& path, cmMessenger* messenger);
void AddGlobCacheEntry(bool recurse, bool listDirectories,
bool followSymlinks, const std::string& relative,
const std::string& expression,
const std::vector<std::string>& files,
const std::string& variable,
- cmListFileBacktrace const& bt);
+ cmListFileBacktrace const& bt,
+ cmMessenger* messenger);
cmPropertyDefinitionMap PropertyDefinitions;
std::vector<std::string> EnabledLanguages;
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index f44fcf7..e5935b8 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -526,7 +526,7 @@ bool HandleLengthCommand(std::vector<std::string> const& args,
size_t length = stringValue.size();
char buffer[1024];
- sprintf(buffer, "%d", static_cast<int>(length));
+ snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(length));
status.GetMakefile().AddDefinition(variableName, buffer);
return true;
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 1934393..effb837 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -540,7 +540,7 @@ size_t cmSystemTools::CalculateCommandLineLengthLimit()
#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
+ // The value in climits 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);
@@ -1158,39 +1158,26 @@ void cmSystemTools::MoveFileIfDifferent(const std::string& source,
RemoveFile(source);
}
+#ifndef CMAKE_BOOTSTRAP
std::string cmSystemTools::ComputeFileHash(const std::string& source,
cmCryptoHash::Algo algo)
{
-#if !defined(CMAKE_BOOTSTRAP)
cmCryptoHash hash(algo);
return hash.HashFile(source);
-#else
- (void)source;
- cmSystemTools::Message("hashsum not supported in bootstrapping mode",
- "Error");
- return std::string();
-#endif
}
std::string cmSystemTools::ComputeStringMD5(const std::string& input)
{
-#if !defined(CMAKE_BOOTSTRAP)
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
return md5.HashString(input);
-#else
- (void)input;
- cmSystemTools::Message("md5sum not supported in bootstrapping mode",
- "Error");
- return "";
-#endif
}
+# ifdef _WIN32
std::string cmSystemTools::ComputeCertificateThumbprint(
const std::string& source)
{
std::string thumbprint;
-#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
CRYPT_INTEGER_BLOB cryptBlob;
HCERTSTORE certStore = NULL;
PCCERT_CONTEXT certContext = NULL;
@@ -1247,14 +1234,11 @@ std::string cmSystemTools::ComputeCertificateThumbprint(
}
CloseHandle(certFile);
}
-#else
- (void)source;
- cmSystemTools::Message("ComputeCertificateThumbprint is not implemented",
- "Error");
-#endif
return thumbprint;
}
+# endif
+#endif
void cmSystemTools::Glob(const std::string& directory,
const std::string& regexp,
@@ -1693,7 +1677,8 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);
if ((p == nullptr) || (*p == '\0')) {
- sprintf(tmp, "%lu ", static_cast<unsigned long>(archive_entry_uid(entry)));
+ snprintf(tmp, sizeof(tmp), "%lu ",
+ static_cast<unsigned long>(archive_entry_uid(entry)));
p = tmp;
}
w = strlen(p);
@@ -1707,7 +1692,8 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
fprintf(out, "%s", p);
w = strlen(p);
} else {
- sprintf(tmp, "%lu", static_cast<unsigned long>(archive_entry_gid(entry)));
+ snprintf(tmp, sizeof(tmp), "%lu",
+ static_cast<unsigned long>(archive_entry_gid(entry)));
w = strlen(tmp);
fprintf(out, "%s", tmp);
}
@@ -1721,15 +1707,15 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
archive_entry_filetype(entry) == AE_IFBLK) {
unsigned long rdevmajor = archive_entry_rdevmajor(entry);
unsigned long rdevminor = archive_entry_rdevminor(entry);
- sprintf(tmp, "%lu,%lu", rdevmajor, rdevminor);
+ snprintf(tmp, sizeof(tmp), "%lu,%lu", rdevmajor, rdevminor);
} else {
/*
* Note the use of platform-dependent macros to format
* the filesize here. We need the format string and the
* corresponding type for the cast.
*/
- sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
- static_cast<BSDTAR_FILESIZE_TYPE>(archive_entry_size(entry)));
+ snprintf(tmp, sizeof(tmp), BSDTAR_FILESIZE_PRINTF,
+ static_cast<BSDTAR_FILESIZE_TYPE>(archive_entry_size(entry)));
}
if (w + strlen(tmp) >= gs_width) {
gs_width = w + strlen(tmp) + 1;
@@ -2496,8 +2482,8 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
return false;
}
-std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
- cm::string_view const& want)
+static std::string::size_type cmSystemToolsFindRPath(
+ cm::string_view const& have, cm::string_view const& want)
{
std::string::size_type pos = 0;
while (pos < have.size()) {
@@ -2694,11 +2680,11 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
}
}
-cm::optional<bool> ChangeRPathELF(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath,
- std::string* emsg, bool* changed)
+static cm::optional<bool> ChangeRPathELF(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath,
+ std::string* emsg, bool* changed)
{
auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
cm::optional<std::string>& outRPath,
@@ -3306,7 +3292,7 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes)
case ' ':
case '=':
case '%':
- sprintf(hexCh, "%%%02X", static_cast<int>(c));
+ snprintf(hexCh, sizeof(hexCh), "%%%02X", static_cast<int>(c));
break;
case '/':
if (escapeSlashes) {
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 715724c..19dabe8 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -179,6 +179,7 @@ public:
static void MoveFileIfDifferent(const std::string& source,
const std::string& destination);
+#ifndef CMAKE_BOOTSTRAP
//! Compute the hash of a file
static std::string ComputeFileHash(const std::string& source,
cmCryptoHash::Algo algo);
@@ -186,8 +187,11 @@ public:
/** Compute the md5sum of a string. */
static std::string ComputeStringMD5(const std::string& input);
+# ifdef _WIN32
//! Get the SHA thumbprint for a certificate file
static std::string ComputeCertificateThumbprint(const std::string& source);
+# endif
+#endif
/**
* Run a single executable command
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 45e23d3..6059055 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -14,19 +14,21 @@
#include <cm/memory>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmMessenger.h"
#include "cmProperty.h"
+#include "cmPropertyDefinition.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmSourceFile.h"
@@ -80,9 +82,8 @@ const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>(
}
template <>
-cmValue cmTargetPropertyComputer::GetSources<cmTarget>(
- cmTarget const* tgt, cmMessenger* messenger,
- cmListFileBacktrace const& context)
+cmValue cmTargetPropertyComputer::GetSources<cmTarget>(cmTarget const* tgt,
+ cmMakefile const& mf)
{
cmBTStringRange entries = tgt->GetSourceEntries();
if (entries.empty()) {
@@ -109,7 +110,7 @@ cmValue cmTargetPropertyComputer::GetSources<cmTarget>(
bool noMessage = true;
std::ostringstream e;
MessageType messageType = MessageType::AUTHOR_WARNING;
- switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0051)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
noMessage = false;
@@ -130,7 +131,7 @@ cmValue cmTargetPropertyComputer::GetSources<cmTarget>(
"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);
+ mf.IssueMessage(messageType, e.str());
}
if (addContent) {
ss << sep;
@@ -201,8 +202,14 @@ public:
std::vector<BT<std::string>> LinkOptionsEntries;
std::vector<BT<std::string>> LinkDirectoriesEntries;
std::vector<BT<std::string>> LinkImplementationPropertyEntries;
+ std::vector<BT<std::string>> LinkInterfacePropertyEntries;
+ std::vector<BT<std::string>> LinkInterfaceDirectPropertyEntries;
+ std::vector<BT<std::string>> LinkInterfaceDirectExcludePropertyEntries;
+ std::vector<BT<std::string>> HeaderSetsEntries;
+ std::vector<BT<std::string>> InterfaceHeaderSetsEntries;
std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
TLLCommands;
+ std::map<std::string, cmFileSet> FileSets;
cmListFileBacktrace Backtrace;
bool CheckImportedLibName(std::string const& prop,
@@ -396,6 +403,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
initProp("XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING");
+ initProp("XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE");
initProp("XCODE_SCHEME_THREAD_SANITIZER");
initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
@@ -467,6 +475,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp(property);
}
}
+ if (!this->IsImported()) {
+ initProp("LINK_LIBRARIES_ONLY_TARGETS");
+ }
}
// Save the backtrace of target construction.
@@ -522,6 +533,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
}
+ if (!this->IsImported()) {
+ initProp("DOTNET_SDK");
+ }
+
if (this->impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
initProp("DOTNET_TARGET_FRAMEWORK");
initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
@@ -546,6 +561,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
}
}
+
+ for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
+ if (prop.first.second == cmProperty::TARGET &&
+ !prop.second.GetInitializeFromVariable().empty()) {
+ if (auto value =
+ mf->GetDefinition(prop.second.GetInitializeFromVariable())) {
+ this->SetProperty(prop.first.first, value);
+ }
+ }
+ }
}
cmTarget::cmTarget(cmTarget&&) noexcept = default;
@@ -1114,6 +1139,31 @@ cmBTStringRange cmTarget::GetLinkImplementationEntries() const
return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
}
+cmBTStringRange cmTarget::GetLinkInterfaceEntries() const
+{
+ return cmMakeRange(this->impl->LinkInterfacePropertyEntries);
+}
+
+cmBTStringRange cmTarget::GetLinkInterfaceDirectEntries() const
+{
+ return cmMakeRange(this->impl->LinkInterfaceDirectPropertyEntries);
+}
+
+cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const
+{
+ return cmMakeRange(this->impl->LinkInterfaceDirectExcludePropertyEntries);
+}
+
+cmBTStringRange cmTarget::GetHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->HeaderSetsEntries);
+}
+
+cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->InterfaceHeaderSetsEntries);
+}
+
namespace {
#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
MAKE_PROP(C_STANDARD);
@@ -1143,6 +1193,13 @@ MAKE_PROP(BINARY_DIR);
MAKE_PROP(SOURCE_DIR);
MAKE_PROP(FALSE);
MAKE_PROP(TRUE);
+MAKE_PROP(HEADER_DIRS);
+MAKE_PROP(HEADER_SET);
+MAKE_PROP(HEADER_SETS);
+MAKE_PROP(INTERFACE_HEADER_SETS);
+MAKE_PROP(INTERFACE_LINK_LIBRARIES);
+MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT);
+MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE);
#undef MAKE_PROP
}
@@ -1162,6 +1219,21 @@ std::string ConvertToString<cmValue>(cmValue value)
{
return std::string(*value);
}
+
+template <typename ValueType>
+bool StringIsEmpty(ValueType value);
+
+template <>
+bool StringIsEmpty<const char*>(const char* value)
+{
+ return cmValue::IsEmpty(value);
+}
+
+template <>
+bool StringIsEmpty<cmValue>(cmValue value)
+{
+ return value.IsEmpty();
+}
}
template <typename ValueType>
@@ -1253,6 +1325,25 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
}
+ } else if (prop == propINTERFACE_LINK_LIBRARIES) {
+ this->impl->LinkInterfacePropertyEntries.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
+ }
+ } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
+ this->impl->LinkInterfaceDirectPropertyEntries.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
+ }
+ } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
+ this->impl->LinkInterfaceDirectExcludePropertyEntries.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
+ lfbt);
+ }
} else if (prop == propSOURCES) {
this->impl->SourceEntries.clear();
if (value) {
@@ -1325,6 +1416,104 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
} else {
this->impl->LanguageStandardProperties.erase(prop);
}
+ } else if (prop == propHEADER_DIRS) {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->ClearDirectoryEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (prop == propHEADER_SET) {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->ClearFileEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->ClearDirectoryEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->ClearFileEntries();
+ if (!StringIsEmpty(value)) {
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ }
+ } else if (prop == propHEADER_SETS) {
+ if (value) {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ }
+ this->impl->HeaderSetsEntries.clear();
+ if (!StringIsEmpty(value)) {
+ this->impl->HeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ }
+ } else if (prop == propINTERFACE_HEADER_SETS) {
+ if (value) {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ }
+ this->impl->InterfaceHeaderSetsEntries.clear();
+ if (!StringIsEmpty(value)) {
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ }
} else {
this->impl->Properties.SetProperty(prop, value);
}
@@ -1408,6 +1597,22 @@ void cmTarget::AppendProperty(const std::string& prop,
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
}
+ } else if (prop == propINTERFACE_LINK_LIBRARIES) {
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
+ }
+ } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
+ }
+ } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
+ if (!value.empty()) {
+ cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
+ this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
+ lfbt);
+ }
} else if (prop == "SOURCES") {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->SourceEntries.emplace_back(value, lfbt);
@@ -1419,6 +1624,82 @@ void cmTarget::AppendProperty(const std::string& prop,
prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be appended.");
+ } else if (prop == "HEADER_DIRS") {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->AddDirectoryEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (prop == "HEADER_SET") {
+ auto* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The default header set has not yet been created.");
+ return;
+ }
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ auto fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "Header set name cannot be empty.");
+ return;
+ }
+ auto* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", fileSetName,
+ "\" has not yet been created."));
+ return;
+ }
+ fileSet->AddFileEntry(
+ BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
+ } else if (prop == "HEADER_SETS") {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ this->impl->HeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
+ } else if (prop == "INTERFACE_HEADER_SETS") {
+ for (auto const& name : cmExpandedList(value)) {
+ if (!this->GetFileSet(name)) {
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Header set \"", name, "\" has not yet been created."));
+ return;
+ }
+ }
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ value, this->impl->Makefile->GetBacktrace());
} else {
this->impl->Properties.AppendProperty(prop, value, asString);
}
@@ -1608,10 +1889,9 @@ void cmTarget::CheckProperty(const std::string& prop,
}
cmValue cmTarget::GetComputedProperty(const std::string& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context) const
+ cmMakefile& mf) const
{
- return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
+ return cmTargetPropertyComputer::GetProperty(this, prop, mf);
}
cmValue cmTarget::GetProperty(const std::string& prop) const
@@ -1637,7 +1917,14 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
propNAME,
propBINARY_DIR,
propSOURCE_DIR,
- propSOURCES
+ propSOURCES,
+ propHEADER_DIRS,
+ propHEADER_SET,
+ propHEADER_SETS,
+ propINTERFACE_HEADER_SETS,
+ propINTERFACE_LINK_LIBRARIES,
+ propINTERFACE_LINK_LIBRARIES_DIRECT,
+ propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
};
if (specialProps.count(prop)) {
if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
@@ -1658,6 +1945,34 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
return cmValue(output);
}
+ if (prop == propINTERFACE_LINK_LIBRARIES) {
+ if (this->impl->LinkInterfacePropertyEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->impl->LinkInterfacePropertyEntries, ";");
+ return cmValue(output);
+ }
+ if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
+ if (this->impl->LinkInterfaceDirectPropertyEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->impl->LinkInterfaceDirectPropertyEntries, ";");
+ return cmValue(output);
+ }
+ if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
+ if (this->impl->LinkInterfaceDirectExcludePropertyEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output =
+ cmJoin(this->impl->LinkInterfaceDirectExcludePropertyEntries, ";");
+ return cmValue(output);
+ }
// the type property returns what type the target is
if (prop == propTYPE) {
return cmValue(cmState::GetTargetTypeName(this->GetType()));
@@ -1763,6 +2078,60 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
.GetDirectory()
.GetCurrentSource());
}
+ if (prop == propHEADER_DIRS) {
+ auto const* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propHEADER_SET) {
+ auto const* fileSet = this->GetFileSet("HEADERS");
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetFileEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propHEADER_SETS) {
+ static std::string output;
+ output = cmJoin(this->impl->HeaderSetsEntries, ";"_s);
+ return cmValue(output);
+ }
+ if (prop == propINTERFACE_HEADER_SETS) {
+ static std::string output;
+ output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s);
+ return cmValue(output);
+ }
+ }
+ if (cmHasLiteralPrefix(prop, "HEADER_DIRS_")) {
+ std::string fileSetName = prop.substr(cmStrLen("HEADER_DIRS_"));
+ if (fileSetName.empty()) {
+ return nullptr;
+ }
+ auto const* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetDirectoryEntries(), ";"_s);
+ return cmValue(output);
+ }
+ if (cmHasLiteralPrefix(prop, "HEADER_SET_")) {
+ std::string fileSetName = prop.substr(cmStrLen("HEADER_SET_"));
+ if (fileSetName.empty()) {
+ return nullptr;
+ }
+ auto const* fileSet = this->GetFileSet(fileSetName);
+ if (!fileSet) {
+ return nullptr;
+ }
+ static std::string output;
+ output = cmJoin(fileSet->GetFileEntries(), ";"_s);
+ return cmValue(output);
}
cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
@@ -2019,6 +2388,59 @@ std::string cmTarget::ImportedGetFullPath(
return result;
}
+const cmFileSet* cmTarget::GetFileSet(const std::string& name) const
+{
+ auto it = this->impl->FileSets.find(name);
+ return it == this->impl->FileSets.end() ? nullptr : &it->second;
+}
+
+cmFileSet* cmTarget::GetFileSet(const std::string& name)
+{
+ auto it = this->impl->FileSets.find(name);
+ return it == this->impl->FileSets.end() ? nullptr : &it->second;
+}
+
+std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
+ const std::string& name, const std::string& type)
+{
+ auto result =
+ this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type)));
+ return std::make_pair(&result.first->second, result.second);
+}
+
+std::string cmTarget::GetFileSetsPropertyName(const std::string& type)
+{
+ if (type == "HEADERS") {
+ return "HEADER_SETS";
+ }
+ return "";
+}
+
+std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type)
+{
+ if (type == "HEADERS") {
+ return "INTERFACE_HEADER_SETS";
+ }
+ return "";
+}
+
+std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
+{
+ std::vector<std::string> result;
+ auto inserter = std::back_inserter(result);
+
+ auto appendEntries = [=](const std::vector<BT<std::string>>& entries) {
+ for (auto const& entry : entries) {
+ auto expanded = cmExpandedList(entry.Value);
+ std::copy(expanded.begin(), expanded.end(), inserter);
+ }
+ };
+
+ appendEntries(this->impl->InterfaceHeaderSetsEntries);
+
+ return result;
+}
+
bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
std::string const& value) const
{
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 95aa4d3..0cdd2fc 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -12,7 +12,6 @@
#include <vector>
#include "cmAlgorithms.h"
-#include "cmListFileCache.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -20,15 +19,22 @@
#include "cmValue.h"
class cmCustomCommand;
+class cmFileSet;
class cmGlobalGenerator;
class cmInstallTargetGenerator;
+class cmListFileBacktrace;
+class cmListFileContext;
class cmMakefile;
-class cmMessenger;
class cmPropertyMap;
class cmSourceFile;
class cmTargetExport;
class cmTargetInternals;
+template <typename T>
+class BT;
+template <typename T>
+class BTs;
+
/** \class cmTarget
* \brief Represent a library or executable target loaded from a makefile.
*
@@ -184,8 +190,7 @@ public:
std::string const& GetSafeProperty(std::string const& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
- cmValue GetComputedProperty(const std::string& prop, cmMessenger* messenger,
- cmListFileBacktrace const& context) const;
+ cmValue GetComputedProperty(const std::string& prop, cmMakefile& mf) const;
//! Get all properties
cmPropertyMap const& GetProperties() const;
@@ -263,6 +268,14 @@ public:
cmBTStringRange GetLinkImplementationEntries() const;
+ cmBTStringRange GetLinkInterfaceEntries() const;
+ cmBTStringRange GetLinkInterfaceDirectEntries() const;
+ cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
+
+ cmBTStringRange GetHeaderSetsEntries() const;
+
+ cmBTStringRange GetInterfaceHeaderSetsEntries() const;
+
std::string ImportedGetFullPath(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
@@ -271,6 +284,16 @@ public:
bool operator()(cmTarget const* t1, cmTarget const* t2) const;
};
+ const cmFileSet* GetFileSet(const std::string& name) const;
+ cmFileSet* GetFileSet(const std::string& name);
+ std::pair<cmFileSet*, bool> GetOrCreateFileSet(const std::string& name,
+ const std::string& type);
+
+ std::vector<std::string> GetAllInterfaceFileSets() const;
+
+ static std::string GetFileSetsPropertyName(const std::string& type);
+ static std::string GetInterfaceFileSetsPropertyName(const std::string& type);
+
private:
template <typename ValueType>
void StoreProperty(const std::string& prop, ValueType value);
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index 36702bd..9027409 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -6,6 +6,8 @@
#include <set>
+#include "cmListFileCache.h"
+
class cmGeneratorTarget;
/** One edge in the global target dependency graph.
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 19fc931..885ac74 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -6,7 +6,9 @@
#include <string>
+class cmFileSet;
class cmGeneratorTarget;
+class cmInstallFileSetGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
@@ -29,6 +31,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
+ std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators;
///@}
bool NamelinkOnly = false;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index e15c941..94fcdd9 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -2,11 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetLinkLibrariesCommand.h"
+#include <cassert>
#include <memory>
#include <sstream>
#include <unordered_set>
#include <utility>
+#include <cm/optional>
+
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
@@ -178,123 +181,156 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
// specification if the keyword is encountered as the first argument.
ProcessingState currentProcessingState = ProcessingLinkLibraries;
+ // Accumulate consectuive non-keyword arguments into one entry in
+ // order to handle unquoted generator expressions containing ';'.
+ cm::optional<std::string> currentEntry;
+ auto processCurrentEntry = [&]() -> bool {
+ if (currentEntry) {
+ assert(!haveLLT);
+ if (!tll.HandleLibrary(currentProcessingState, *currentEntry,
+ GENERAL_LibraryType)) {
+ return false;
+ }
+ currentEntry = cm::nullopt;
+ }
+ return true;
+ };
+ auto extendCurrentEntry = [&currentEntry](std::string const& arg) {
+ if (currentEntry) {
+ currentEntry = cmStrCat(*currentEntry, ';', arg);
+ } else {
+ currentEntry = arg;
+ }
+ };
+
+ // Keep this list in sync with the keyword dispatch below.
+ static std::unordered_set<std::string> const keywords{
+ "LINK_INTERFACE_LIBRARIES",
+ "INTERFACE",
+ "LINK_PUBLIC",
+ "PUBLIC",
+ "LINK_PRIVATE",
+ "PRIVATE",
+ "debug",
+ "optimized",
+ "general",
+ };
+
// 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") {
- currentProcessingState = ProcessingPlainLinkInterface;
- if (i != 1) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The LINK_INTERFACE_LIBRARIES option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- } else if (args[i] == "INTERFACE") {
- if (i != 1 &&
- currentProcessingState != ProcessingKeywordPrivateInterface &&
- currentProcessingState != ProcessingKeywordPublicInterface &&
- currentProcessingState != ProcessingKeywordLinkInterface) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- currentProcessingState = ProcessingKeywordLinkInterface;
- } else if (args[i] == "LINK_PUBLIC") {
- if (i != 1 &&
- currentProcessingState != ProcessingPlainPrivateInterface &&
- currentProcessingState != ProcessingPlainPublicInterface) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- currentProcessingState = ProcessingPlainPublicInterface;
- } else if (args[i] == "PUBLIC") {
- if (i != 1 &&
- currentProcessingState != ProcessingKeywordPrivateInterface &&
- currentProcessingState != ProcessingKeywordPublicInterface &&
- currentProcessingState != ProcessingKeywordLinkInterface) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- currentProcessingState = ProcessingKeywordPublicInterface;
- } else if (args[i] == "LINK_PRIVATE") {
- if (i != 1 && currentProcessingState != ProcessingPlainPublicInterface &&
- currentProcessingState != ProcessingPlainPrivateInterface) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- currentProcessingState = ProcessingPlainPrivateInterface;
- } else if (args[i] == "PRIVATE") {
- if (i != 1 &&
- currentProcessingState != ProcessingKeywordPrivateInterface &&
- currentProcessingState != ProcessingKeywordPublicInterface &&
- currentProcessingState != ProcessingKeywordLinkInterface) {
- mf.IssueMessage(
- MessageType::FATAL_ERROR,
- "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
- "argument, just after the target name.");
- return true;
- }
- currentProcessingState = ProcessingKeywordPrivateInterface;
- } else if (args[i] == "debug") {
- if (haveLLT) {
- LinkLibraryTypeSpecifierWarning(mf, llt, DEBUG_LibraryType);
- }
- llt = DEBUG_LibraryType;
- haveLLT = true;
- } else if (args[i] == "optimized") {
- if (haveLLT) {
- LinkLibraryTypeSpecifierWarning(mf, llt, OPTIMIZED_LibraryType);
+ if (keywords.count(args[i])) {
+ // A keyword argument terminates any preceding accumulated entry.
+ if (!processCurrentEntry()) {
+ return false;
}
- llt = OPTIMIZED_LibraryType;
- haveLLT = true;
- } else if (args[i] == "general") {
- if (haveLLT) {
- LinkLibraryTypeSpecifierWarning(mf, llt, GENERAL_LibraryType);
+
+ // Process this keyword argument.
+ if (args[i] == "LINK_INTERFACE_LIBRARIES") {
+ currentProcessingState = ProcessingPlainLinkInterface;
+ if (i != 1) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The LINK_INTERFACE_LIBRARIES option must appear as the "
+ "second argument, just after the target name.");
+ return true;
+ }
+ } else if (args[i] == "INTERFACE") {
+ if (i != 1 &&
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must "
+ "appear as the second argument, just after the "
+ "target name.");
+ return true;
+ }
+ currentProcessingState = ProcessingKeywordLinkInterface;
+ } else if (args[i] == "LINK_PUBLIC") {
+ if (i != 1 &&
+ currentProcessingState != ProcessingPlainPrivateInterface &&
+ currentProcessingState != ProcessingPlainPublicInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The LINK_PUBLIC or LINK_PRIVATE option must appear as the "
+ "second argument, just after the target name.");
+ return true;
+ }
+ currentProcessingState = ProcessingPlainPublicInterface;
+ } else if (args[i] == "PUBLIC") {
+ if (i != 1 &&
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must "
+ "appear as the second argument, just after the "
+ "target name.");
+ return true;
+ }
+ currentProcessingState = ProcessingKeywordPublicInterface;
+ } else if (args[i] == "LINK_PRIVATE") {
+ if (i != 1 &&
+ currentProcessingState != ProcessingPlainPublicInterface &&
+ currentProcessingState != ProcessingPlainPrivateInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The LINK_PUBLIC or LINK_PRIVATE option must appear as the "
+ "second argument, just after the target name.");
+ return true;
+ }
+ currentProcessingState = ProcessingPlainPrivateInterface;
+ } else if (args[i] == "PRIVATE") {
+ if (i != 1 &&
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must "
+ "appear as the second argument, just after the "
+ "target name.");
+ return true;
+ }
+ currentProcessingState = ProcessingKeywordPrivateInterface;
+ } else if (args[i] == "debug") {
+ if (haveLLT) {
+ LinkLibraryTypeSpecifierWarning(mf, llt, DEBUG_LibraryType);
+ }
+ llt = DEBUG_LibraryType;
+ haveLLT = true;
+ } else if (args[i] == "optimized") {
+ if (haveLLT) {
+ LinkLibraryTypeSpecifierWarning(mf, llt, OPTIMIZED_LibraryType);
+ }
+ llt = OPTIMIZED_LibraryType;
+ haveLLT = true;
+ } else if (args[i] == "general") {
+ if (haveLLT) {
+ LinkLibraryTypeSpecifierWarning(mf, llt, GENERAL_LibraryType);
+ }
+ llt = GENERAL_LibraryType;
+ haveLLT = true;
}
- llt = GENERAL_LibraryType;
- haveLLT = true;
} else if (haveLLT) {
// The link type was specified by the previous argument.
haveLLT = false;
+ assert(!currentEntry);
if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) {
return false;
}
- } else {
- // Lookup old-style cache entry if type is unspecified. So if you
- // do a target_link_libraries(foo optimized bar) it will stay optimized
- // and not use the lookup. As there may be the case where someone has
- // specified that a library is both debug and optimized. (this check is
- // only there for backwards compatibility when mixing projects built
- // with old versions of CMake and new)
llt = GENERAL_LibraryType;
- std::string linkType = cmStrCat(args[0], "_LINK_TYPE");
- cmValue linkTypeString = mf.GetDefinition(linkType);
- if (linkTypeString) {
- if (*linkTypeString == "debug") {
- llt = DEBUG_LibraryType;
- }
- if (*linkTypeString == "optimized") {
- llt = OPTIMIZED_LibraryType;
- }
- }
- if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) {
- return false;
- }
+ } else {
+ // Accumulate this argument in the current entry.
+ extendCurrentEntry(args[i]);
}
}
+ // Process the last accumulated entry, if any.
+ if (!processCurrentEntry()) {
+ return false;
+ }
+
// Make sure the last argument was not a library type specifier.
if (haveLLT) {
mf.IssueMessage(MessageType::FATAL_ERROR,
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 3bd1ea3..391b954 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -155,10 +155,10 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
return false;
}
}
- return this->PopulateTargetProperies(scope, content, prepend, system);
+ return this->PopulateTargetProperties(scope, content, prepend, system);
}
-bool cmTargetPropCommandBase::PopulateTargetProperies(
+bool cmTargetPropCommandBase::PopulateTargetProperties(
const std::string& scope, const std::vector<std::string>& content,
bool prepend, bool system)
{
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index fc24fe8..6bf7c3c 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -40,6 +40,9 @@ protected:
virtual void HandleInterfaceContent(cmTarget* tgt,
const std::vector<std::string>& content,
bool prepend, bool system);
+ virtual bool PopulateTargetProperties(
+ const std::string& scope, const std::vector<std::string>& content,
+ bool prepend, bool system);
private:
virtual void HandleMissingTarget(const std::string& name) = 0;
@@ -52,9 +55,6 @@ private:
bool ProcessContentArgs(std::vector<std::string> const& args,
unsigned int& argIndex, bool prepend, bool system);
- bool PopulateTargetProperies(const std::string& scope,
- const std::vector<std::string>& content,
- bool prepend, bool system);
cmExecutionStatus& Status;
};
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index 9b94142..134b4b6 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -5,19 +5,17 @@
#include <sstream>
+#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmMessenger.h"
#include "cmPolicies.h"
-#include "cmStateSnapshot.h"
bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
- std::string const& tgtName, cmMessenger* messenger,
- cmListFileBacktrace const& context)
+ std::string const& tgtName, cmMakefile const& mf)
{
std::ostringstream e;
const char* modal = nullptr;
MessageType messageType = MessageType::AUTHOR_WARNING;
- switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0026)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
modal = "should";
@@ -38,7 +36,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
<< "\". 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);
+ mf.IssueMessage(messageType, e.str());
}
return messageType != MessageType::FATAL_ERROR;
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index e61a1fc..82c6355 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -6,38 +6,35 @@
#include <string>
-#include "cmListFileCache.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
-class cmMessenger;
+class cmMakefile;
class cmTargetPropertyComputer
{
public:
template <typename Target>
static cmValue GetProperty(Target const* tgt, const std::string& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context)
+ cmMakefile const& mf)
{
- if (cmValue loc = GetLocation(tgt, prop, messenger, context)) {
+ if (cmValue loc = GetLocation(tgt, prop, mf)) {
return loc;
}
if (cmSystemTools::GetFatalErrorOccured()) {
return nullptr;
}
if (prop == "SOURCES") {
- return GetSources(tgt, messenger, context);
+ return GetSources(tgt, mf);
}
return nullptr;
}
private:
static bool HandleLocationPropertyPolicy(std::string const& tgtName,
- cmMessenger* messenger,
- cmListFileBacktrace const& context);
+ cmMakefile const& mf);
template <typename Target>
static const std::string& ComputeLocationForBuild(Target const* tgt);
@@ -47,8 +44,7 @@ private:
template <typename Target>
static cmValue GetLocation(Target const* tgt, std::string const& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context)
+ cmMakefile const& mf)
{
// Watch for special "computed" properties that are dependent on
@@ -61,8 +57,7 @@ private:
static const std::string propLOCATION = "LOCATION";
if (prop == propLOCATION) {
if (!tgt->IsImported() &&
- !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
- context)) {
+ !HandleLocationPropertyPolicy(tgt->GetName(), mf)) {
return nullptr;
}
return cmValue(ComputeLocationForBuild(tgt));
@@ -71,8 +66,7 @@ private:
// Support "LOCATION_<CONFIG>".
if (cmHasLiteralPrefix(prop, "LOCATION_")) {
if (!tgt->IsImported() &&
- !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
- context)) {
+ !HandleLocationPropertyPolicy(tgt->GetName(), mf)) {
return nullptr;
}
std::string configName = prop.substr(9);
@@ -85,8 +79,7 @@ private:
std::string configName(prop.c_str(), prop.size() - 9);
if (configName != "IMPORTED") {
if (!tgt->IsImported() &&
- !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
- context)) {
+ !HandleLocationPropertyPolicy(tgt->GetName(), mf)) {
return nullptr;
}
return cmValue(ComputeLocation(tgt, configName));
@@ -97,6 +90,5 @@ private:
}
template <typename Target>
- static cmValue GetSources(Target const* tgt, cmMessenger* messenger,
- cmListFileBacktrace const& context);
+ static cmValue GetSources(Target const* tgt, cmMakefile const& mf);
};
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 26282ef..b425acb 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -2,12 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetSourcesCommand.h"
+#include <algorithm>
#include <sstream>
+#include <utility>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmArgumentParser.h"
+#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -15,6 +24,20 @@
namespace {
+struct FileSetArgs
+{
+ std::string Type;
+ std::string FileSet;
+ std::vector<std::string> BaseDirs;
+ std::vector<std::string> Files;
+};
+
+auto const FileSetArgsParser = cmArgumentParser<FileSetArgs>()
+ .Bind("TYPE"_s, &FileSetArgs::Type)
+ .Bind("FILE_SET"_s, &FileSetArgs::FileSet)
+ .Bind("BASE_DIRS"_s, &FileSetArgs::BaseDirs)
+ .Bind("FILES"_s, &FileSetArgs::Files);
+
class TargetSourcesImpl : public cmTargetPropCommandBase
{
public:
@@ -26,8 +49,10 @@ protected:
bool prepend, bool system) override
{
this->cmTargetPropCommandBase::HandleInterfaceContent(
- tgt, this->ConvertToAbsoluteContent(tgt, content, true), prepend,
- system);
+ tgt,
+ this->ConvertToAbsoluteContent(tgt, content, IsInterface::Yes,
+ CheckCMP0076::Yes),
+ prepend, system);
}
private:
@@ -43,29 +68,55 @@ private:
const std::vector<std::string>& content,
bool /*prepend*/, bool /*system*/) override
{
- tgt->AppendProperty(
- "SOURCES",
- this->Join(this->ConvertToAbsoluteContent(tgt, content, false)));
+ tgt->AppendProperty("SOURCES",
+ this->Join(this->ConvertToAbsoluteContent(
+ tgt, content, IsInterface::No, CheckCMP0076::Yes)));
return true; // Successfully handled.
}
+ bool PopulateTargetProperties(const std::string& scope,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override
+ {
+ if (!content.empty() && content.front() == "FILE_SET"_s) {
+ return this->HandleFileSetMode(scope, content, prepend, system);
+ }
+ return this->cmTargetPropCommandBase::PopulateTargetProperties(
+ scope, content, prepend, system);
+ }
+
std::string Join(const std::vector<std::string>& content) override
{
return cmJoin(content, ";");
}
+ enum class IsInterface
+ {
+ Yes,
+ No,
+ };
+ enum class CheckCMP0076
+ {
+ Yes,
+ No,
+ };
std::vector<std::string> ConvertToAbsoluteContent(
cmTarget* tgt, const std::vector<std::string>& content,
- bool isInterfaceContent);
+ IsInterface isInterfaceContent, CheckCMP0076 checkCmp0076);
+
+ bool HandleFileSetMode(const std::string& scope,
+ const std::vector<std::string>& content, bool prepend,
+ bool system);
};
std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
cmTarget* tgt, const std::vector<std::string>& content,
- bool isInterfaceContent)
+ IsInterface isInterfaceContent, CheckCMP0076 checkCmp0076)
{
// Skip conversion in case old behavior has been explicitly requested
- if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
- cmPolicies::OLD) {
+ if (checkCmp0076 == CheckCMP0076::Yes &&
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
+ cmPolicies::OLD) {
return content;
}
@@ -76,7 +127,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
std::string absoluteSrc;
if (cmSystemTools::FileIsFullPath(src) ||
cmGeneratorExpression::Find(src) == 0 ||
- (!isInterfaceContent &&
+ (isInterfaceContent == IsInterface::No &&
(this->Makefile->GetCurrentSourceDirectory() ==
tgt->GetMakefile()->GetCurrentSourceDirectory()))) {
absoluteSrc = src;
@@ -95,28 +146,33 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
bool issueMessage = true;
bool useAbsoluteContent = false;
std::ostringstream e;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
- case cmPolicies::WARN:
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
- break;
- case cmPolicies::OLD:
- issueMessage = false;
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- this->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
- break;
- case cmPolicies::NEW: {
- issueMessage = false;
- useAbsoluteContent = true;
- break;
+ if (checkCmp0076 == CheckCMP0076::Yes) {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
+ break;
+ case cmPolicies::NEW: {
+ issueMessage = false;
+ useAbsoluteContent = true;
+ break;
+ }
}
+ } else {
+ issueMessage = false;
+ useAbsoluteContent = true;
}
if (issueMessage) {
- if (isInterfaceContent) {
+ if (isInterfaceContent == IsInterface::Yes) {
e << "An interface source of target \"" << tgt->GetName()
<< "\" has a relative path.";
} else {
@@ -129,6 +185,138 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
return useAbsoluteContent ? absoluteContent : content;
}
+bool TargetSourcesImpl::HandleFileSetMode(
+ const std::string& scope, const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/)
+{
+ std::vector<std::string> unparsed;
+ auto args = FileSetArgsParser.Parse(content, &unparsed);
+
+ if (!unparsed.empty()) {
+ this->SetError(
+ cmStrCat("Unrecognized keyword: \"", unparsed.front(), "\""));
+ return false;
+ }
+
+ if (args.FileSet.empty()) {
+ this->SetError("FILE_SET must not be empty");
+ return false;
+ }
+
+ if (this->Target->GetType() == cmStateEnums::UTILITY) {
+ this->SetError("FILE_SETs may not be added to custom targets");
+ return false;
+ }
+
+ bool const isDefault = args.Type == args.FileSet ||
+ (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z');
+ std::string type = isDefault ? args.FileSet : args.Type;
+
+ auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type);
+ if (fileSet.second) {
+ if (!isDefault) {
+ if (args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z') {
+ this->SetError(
+ "Non-default file set name must not start with a capital letter");
+ return false;
+ }
+ }
+ if (type.empty()) {
+ this->SetError("Must specify a TYPE when creating file set");
+ return false;
+ }
+ if (type != "HEADERS"_s) {
+ this->SetError("File set TYPE may only be \"HEADERS\"");
+ return false;
+ }
+
+ if (args.BaseDirs.empty()) {
+ args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory());
+ }
+
+ if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
+ this->Target->AppendProperty(cmTarget::GetFileSetsPropertyName(type),
+ args.FileSet);
+ }
+ if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
+ this->Target->AppendProperty(
+ cmTarget::GetInterfaceFileSetsPropertyName(type), args.FileSet);
+ }
+ } else {
+ type = fileSet.first->GetType();
+ if (!args.Type.empty() && args.Type != type) {
+ this->SetError(cmStrCat(
+ "Type \"", args.Type, "\" for file set \"", fileSet.first->GetName(),
+ "\" does not match original type \"", type, "\""));
+ return false;
+ }
+
+ std::string existingScope = "PRIVATE";
+
+ auto const fileSetsProperty = cmTarget::GetFileSetsPropertyName(type);
+ auto const interfaceFileSetsProperty =
+ cmTarget::GetInterfaceFileSetsPropertyName(type);
+ std::vector<std::string> fileSets;
+ std::vector<std::string> interfaceFileSets;
+ cmExpandList(this->Target->GetSafeProperty(fileSetsProperty), fileSets);
+ cmExpandList(this->Target->GetSafeProperty(interfaceFileSetsProperty),
+ interfaceFileSets);
+
+ if (std::find(interfaceFileSets.begin(), interfaceFileSets.end(),
+ args.FileSet) != interfaceFileSets.end()) {
+ existingScope = "INTERFACE";
+ }
+ if (std::find(fileSets.begin(), fileSets.end(), args.FileSet) !=
+ fileSets.end()) {
+ if (existingScope == "INTERFACE"_s) {
+ existingScope = "PUBLIC";
+ }
+ } else if (existingScope != "INTERFACE"_s) {
+ this->SetError(cmStrCat("File set \"", args.FileSet, "\" is not in ",
+ fileSetsProperty, " or ",
+ interfaceFileSetsProperty));
+ return false;
+ }
+
+ if (scope != existingScope) {
+ this->SetError(
+ cmStrCat("Scope ", scope, " for file set \"", args.FileSet,
+ "\" does not match original scope ", existingScope));
+ return false;
+ }
+ }
+
+ auto files = this->Join(this->ConvertToAbsoluteContent(
+ this->Target, args.Files, IsInterface::Yes, CheckCMP0076::No));
+ if (!files.empty()) {
+ fileSet.first->AddFileEntry(
+ BT<std::string>(files, this->Makefile->GetBacktrace()));
+ }
+
+ auto baseDirectories = this->Join(this->ConvertToAbsoluteContent(
+ this->Target, args.BaseDirs, IsInterface::Yes, CheckCMP0076::No));
+ if (!baseDirectories.empty()) {
+ fileSet.first->AddDirectoryEntry(
+ BT<std::string>(baseDirectories, this->Makefile->GetBacktrace()));
+ if (type == "HEADERS"_s) {
+ for (auto const& dir : cmExpandedList(baseDirectories)) {
+ auto interfaceDirectoriesGenex =
+ cmStrCat("$<BUILD_INTERFACE:", dir, ">");
+ if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
+ this->Target->AppendProperty("INCLUDE_DIRECTORIES",
+ interfaceDirectoriesGenex);
+ }
+ if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
+ this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
+ interfaceDirectoriesGenex);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
} // namespace
bool cmTargetSourcesCommand(std::vector<std::string> const& args,
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 3826577..e2b6c20 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -17,18 +17,27 @@
#include <cstdlib>
#include <cstring>
#include <sstream>
+#include <utility>
#ifdef __MINGW32__
# include <libloaderapi.h>
#endif
+#include <cm3p/uv.h>
+
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
std::string cmTimestamp::CurrentTime(const std::string& formatString,
bool utcFlag) const
{
- time_t currentTimeT = time(nullptr);
+ // get current time with microsecond resolution
+ uv_timeval64_t timeval;
+ uv_gettimeofday(&timeval);
+ auto currentTimeT = static_cast<time_t>(timeval.tv_sec);
+ auto microseconds = static_cast<uint32_t>(timeval.tv_usec);
+
+ // check for override via SOURCE_DATE_EPOCH for reproducible builds
std::string source_date_epoch;
cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
if (!source_date_epoch.empty()) {
@@ -38,12 +47,15 @@ std::string cmTimestamp::CurrentTime(const std::string& formatString,
cmSystemTools::Error("Cannot parse SOURCE_DATE_EPOCH as integer");
exit(27);
}
+ // SOURCE_DATE_EPOCH has only a resolution in the seconds range
+ microseconds = 0;
}
if (currentTimeT == time_t(-1)) {
return std::string();
}
- return this->CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
+ return this->CreateTimestampFromTimeT(currentTimeT, microseconds,
+ formatString, utcFlag);
}
std::string cmTimestamp::FileModificationTime(const char* path,
@@ -57,11 +69,32 @@ std::string cmTimestamp::FileModificationTime(const char* path,
return std::string();
}
- time_t mtime = cmsys::SystemTools::ModifiedTime(real_path);
- return this->CreateTimestampFromTimeT(mtime, formatString, utcFlag);
+ // use libuv's implementation of stat(2) to get the file information
+ time_t mtime = 0;
+ uint32_t microseconds = 0;
+ uv_fs_t req;
+ if (uv_fs_stat(nullptr, &req, real_path.c_str(), nullptr) == 0) {
+ mtime = static_cast<time_t>(req.statbuf.st_mtim.tv_sec);
+ // tv_nsec has nanosecond resolution, but we truncate it to microsecond
+ // resolution in order to be consistent with cmTimestamp::CurrentTime()
+ microseconds = static_cast<uint32_t>(req.statbuf.st_mtim.tv_nsec / 1000);
+ }
+ uv_fs_req_cleanup(&req);
+
+ return this->CreateTimestampFromTimeT(mtime, microseconds, formatString,
+ utcFlag);
+}
+
+std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
+ std::string formatString,
+ bool utcFlag) const
+{
+ return this->CreateTimestampFromTimeT(timeT, 0, std::move(formatString),
+ utcFlag);
}
std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
+ const uint32_t microseconds,
std::string formatString,
bool utcFlag) const
{
@@ -95,7 +128,8 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
: static_cast<char>(0);
if (c1 == '%' && c2 != 0) {
- result += this->AddTimestampComponent(c2, timeStruct, timeT);
+ result +=
+ this->AddTimestampComponent(c2, timeStruct, timeT, microseconds);
++i;
} else {
result += c1;
@@ -144,9 +178,9 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
#endif
}
-std::string cmTimestamp::AddTimestampComponent(char flag,
- struct tm& timeStruct,
- const time_t timeT) const
+std::string cmTimestamp::AddTimestampComponent(
+ char flag, struct tm& timeStruct, const time_t timeT,
+ const uint32_t microseconds) const
{
std::string formatString = cmStrCat('%', flag);
@@ -180,13 +214,19 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
const time_t unixEpoch = this->CreateUtcTimeTFromTm(tmUnixEpoch);
if (unixEpoch == -1) {
cmSystemTools::Error(
- "Error generating UNIX epoch in "
- "STRING(TIMESTAMP ...). Please, file a bug report against CMake");
+ "Error generating UNIX epoch in string(TIMESTAMP ...) or "
+ "file(TIMESTAMP ...). Please, file a bug report against CMake");
return std::string();
}
return std::to_string(static_cast<long int>(difftime(timeT, unixEpoch)));
}
+ case 'f': // microseconds
+ {
+ // clip number to 6 digits and pad with leading zeros
+ std::string microsecs = std::to_string(microseconds % 1000000);
+ return std::string(6 - microsecs.length(), '0') + microsecs;
+ }
default: {
return formatString;
}
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index 0e2c200..ada5006 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstdint>
#include <ctime>
#include <string>
@@ -23,9 +24,14 @@ public:
std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString,
bool utcFlag) const;
+ std::string CreateTimestampFromTimeT(time_t timeT, uint32_t microseconds,
+ std::string formatString,
+ bool utcFlag) const;
+
private:
time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
std::string AddTimestampComponent(char flag, struct tm& timeStruct,
- time_t timeT) const;
+ time_t timeT,
+ uint32_t microseconds = 0) const;
};
diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx
index 4032596..81a6507 100644
--- a/Source/cmTransformDepfile.cxx
+++ b/Source/cmTransformDepfile.cxx
@@ -4,7 +4,6 @@
#include <algorithm>
#include <functional>
-#include <memory>
#include <string>
#include <type_traits>
#include <utility>
@@ -95,14 +94,16 @@ void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,
// Write the format expected by MSBuild CustomBuild AdditionalInputs.
const char* sep = "";
- for (std::string path : content.front().paths) {
- if (!cmSystemTools::FileIsFullPath(path)) {
- path =
- cmSystemTools::CollapseFullPath(path, lg.GetCurrentBinaryDirectory());
+ for (const auto& c : content) {
+ for (std::string path : c.paths) {
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ path = cmSystemTools::CollapseFullPath(path,
+ lg.GetCurrentBinaryDirectory());
+ }
+ std::replace(path.begin(), path.end(), '/', '\\');
+ fout << sep << path;
+ sep = ";";
}
- std::replace(path.begin(), path.end(), '/', '\\');
- fout << sep << path;
- sep = ";";
}
fout << "\n";
}
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index cc9e158..cd468b9 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -211,7 +211,7 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
char retChar[16];
const char* retStr;
if (worked) {
- sprintf(retChar, "%i", retVal);
+ snprintf(retChar, sizeof(retChar), "%i", retVal);
retStr = retChar;
} else {
retStr = "FAILED_TO_RUN";
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index 969a2c2..cbd241b 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVSSetupHelper.h"
+#include <utility>
+
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
@@ -46,17 +48,36 @@ const CLSID CLSID_SetupConfiguration = {
/* clang-format on */
#endif
+namespace {
const WCHAR* Win10SDKComponent =
L"Microsoft.VisualStudio.Component.Windows10SDK";
const WCHAR* Win81SDKComponent =
L"Microsoft.VisualStudio.Component.Windows81SDK";
const WCHAR* ComponentType = L"Component";
+bool LoadVSInstanceVCToolsetVersion(VSInstanceInfo& vsInstanceInfo)
+{
+ std::string const vcRoot = vsInstanceInfo.GetInstallLocation();
+ std::string vcToolsVersionFile =
+ vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt";
+ std::string vcToolsVersion;
+ cmsys::ifstream fin(vcToolsVersionFile.c_str());
+ if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
+ return false;
+ }
+ vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
+ std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
+ if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
+ return false;
+ }
+ vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
+ return true;
+}
+}
+
std::string VSInstanceInfo::GetInstallLocation() const
{
- std::string loc = cmsys::Encoding::ToNarrow(this->VSInstallLocation);
- cmSystemTools::ConvertToUnixSlashes(loc);
- return loc;
+ return this->VSInstallLocation;
}
cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version)
@@ -83,10 +104,12 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper()
CoUninitialize();
}
-bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation)
+bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation,
+ std::string const& vsInstallVersion)
{
this->SpecifiedVSInstallLocation = vsInstallLocation;
cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation);
+ this->SpecifiedVSInstallVersion = vsInstallVersion;
chosenInstanceInfo = VSInstanceInfo();
return this->EnumerateAndChooseVSInstance();
}
@@ -152,29 +175,17 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
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;
- }
+ vsInstanceInfo.Version =
+ cmsys::Encoding::ToNarrow(std::wstring(bstrVersion));
}
// Reboot may have been required before the installation path was created.
@@ -183,26 +194,15 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
if (FAILED(pInstance->GetInstallationPath(&bstrInstallationPath))) {
return false;
} else {
- vsInstanceInfo.VSInstallLocation = std::wstring(bstrInstallationPath);
+ vsInstanceInfo.VSInstallLocation =
+ cmsys::Encoding::ToNarrow(std::wstring(bstrInstallationPath));
+ cmSystemTools::ConvertToUnixSlashes(vsInstanceInfo.VSInstallLocation);
}
}
// Check if a compiler is installed with this instance.
- {
- std::string const vcRoot = vsInstanceInfo.GetInstallLocation();
- std::string vcToolsVersionFile =
- vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt";
- std::string vcToolsVersion;
- cmsys::ifstream fin(vcToolsVersionFile.c_str());
- if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
- return false;
- }
- vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
- std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
- if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
- return false;
- }
- vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
+ if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) {
+ return false;
}
// Reboot may have been required before the product package was registered
@@ -264,7 +264,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceVersion(std::string& vsInstanceVersion)
bool isInstalled = this->EnumerateAndChooseVSInstance();
if (isInstalled) {
- vsInstanceVersion = cmsys::Encoding::ToNarrow(chosenInstanceInfo.Version);
+ vsInstanceVersion = chosenInstanceInfo.Version;
}
return isInstalled;
@@ -298,7 +298,7 @@ bool cmVSSetupAPIHelper::IsEWDKEnabled()
bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
{
bool isVSInstanceExists = false;
- if (chosenInstanceInfo.VSInstallLocation.compare(L"") != 0) {
+ if (chosenInstanceInfo.VSInstallLocation.compare("") != 0) {
return true;
}
@@ -311,12 +311,11 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
if (envVSVersion.empty() || envVsInstallDir.empty())
return false;
- chosenInstanceInfo.VSInstallLocation =
- std::wstring(envVsInstallDir.begin(), envVsInstallDir.end());
- chosenInstanceInfo.Version =
- std::wstring(envVSVersion.begin(), envVSVersion.end());
- chosenInstanceInfo.VCToolsetVersion = envVSVersion;
- chosenInstanceInfo.ullVersion = std::stoi(envVSVersion);
+ chosenInstanceInfo.VSInstallLocation = envVsInstallDir;
+ chosenInstanceInfo.Version = envVSVersion;
+ if (!LoadVSInstanceVCToolsetVersion(chosenInstanceInfo)) {
+ return false;
+ }
chosenInstanceInfo.IsWin10SDKInstalled = true;
chosenInstanceInfo.IsWin81SDKInstalled = !envWindowsSdkDir81.empty();
return true;
@@ -343,7 +342,9 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
return false;
}
- std::wstring const wantVersion = std::to_wstring(this->Version) + L'.';
+ std::string const wantVersion = std::to_string(this->Version) + '.';
+
+ bool specifiedLocationNotSpecifiedVersion = false;
SmartCOMPtr<ISetupInstance> instance;
while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) {
@@ -371,6 +372,16 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
std::string currentVSLocation = instanceInfo.GetInstallLocation();
if (cmSystemTools::ComparePath(currentVSLocation,
this->SpecifiedVSInstallLocation)) {
+ if (this->SpecifiedVSInstallVersion.empty() ||
+ instanceInfo.Version == this->SpecifiedVSInstallVersion) {
+ chosenInstanceInfo = instanceInfo;
+ return true;
+ }
+ specifiedLocationNotSpecifiedVersion = true;
+ }
+ } else if (!this->SpecifiedVSInstallVersion.empty()) {
+ // We are looking for a specific version.
+ if (instanceInfo.Version == this->SpecifiedVSInstallVersion) {
chosenInstanceInfo = instanceInfo;
return true;
}
@@ -392,6 +403,13 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
}
}
+ if (!this->SpecifiedVSInstallLocation.empty() &&
+ !specifiedLocationNotSpecifiedVersion) {
+ // The VS Installer does not know about the specified location.
+ // Check for one directly on disk.
+ return this->LoadSpecifiedVSInstanceFromDisk();
+ }
+
if (vecVSInstances.size() > 0) {
isVSInstanceExists = true;
int index = ChooseVSInstance(vecVSInstances);
@@ -454,6 +472,32 @@ int cmVSSetupAPIHelper::ChooseVSInstance(
return chosenIndex;
}
+bool cmVSSetupAPIHelper::LoadSpecifiedVSInstanceFromDisk()
+{
+ if (!cmSystemTools::FileIsDirectory(this->SpecifiedVSInstallLocation)) {
+ return false;
+ }
+ VSInstanceInfo vsInstanceInfo;
+ vsInstanceInfo.VSInstallLocation = this->SpecifiedVSInstallLocation;
+ // FIXME: Is there a better way to get SDK information?
+ vsInstanceInfo.IsWin10SDKInstalled = true;
+ vsInstanceInfo.IsWin81SDKInstalled = false;
+
+ if (!this->SpecifiedVSInstallVersion.empty()) {
+ // Assume the version specified by the user is correct.
+ vsInstanceInfo.Version = this->SpecifiedVSInstallVersion;
+ } else {
+ return false;
+ }
+
+ if (!LoadVSInstanceVCToolsetVersion(vsInstanceInfo)) {
+ return false;
+ }
+
+ chosenInstanceInfo = std::move(vsInstanceInfo);
+ return true;
+}
+
bool cmVSSetupAPIHelper::Initialize()
{
if (initializationFailure)
diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h
index 61a3ac7..44c883b 100644
--- a/Source/cmVSSetupHelper.h
+++ b/Source/cmVSSetupHelper.h
@@ -84,11 +84,9 @@ private:
struct VSInstanceInfo
{
- std::wstring InstanceId;
- std::wstring VSInstallLocation;
- std::wstring Version;
+ std::string VSInstallLocation;
+ std::string Version;
std::string VCToolsetVersion;
- ULONGLONG ullVersion = 0; // A.B.C.D = (A<<48)|(B<<32)|(C<<16)|D
bool IsWin10SDKInstalled = false;
bool IsWin81SDKInstalled = false;
@@ -101,7 +99,8 @@ public:
cmVSSetupAPIHelper(unsigned int version);
~cmVSSetupAPIHelper();
- bool SetVSInstance(std::string const& vsInstallLocation);
+ bool SetVSInstance(std::string const& vsInstallLocation,
+ std::string const& vsInstallVersion);
bool IsVSInstalled();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
@@ -118,6 +117,7 @@ private:
bool& bWin10SDK, bool& bWin81SDK);
int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances);
bool EnumerateAndChooseVSInstance();
+ bool LoadSpecifiedVSInstanceFromDisk();
unsigned int Version;
@@ -134,4 +134,5 @@ private:
bool IsEWDKEnabled();
std::string SpecifiedVSInstallLocation;
+ std::string SpecifiedVSInstallVersion;
};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index a871e4c..8ffb664 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudio10TargetGenerator.h"
+#include <algorithm>
+#include <cstdio>
+#include <cstring>
#include <iterator>
#include <set>
+#include <sstream>
#include <cm/memory>
#include <cm/optional>
@@ -13,22 +17,41 @@
#include "windows.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalVisualStudio10Generator.h"
-#include "cmGlobalVisualStudioVersionedGenerator.h"
+#include "cmGlobalVisualStudio7Generator.h"
+#include "cmGlobalVisualStudioGenerator.h"
#include "cmLinkLineDeviceComputer.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
#include "cmLocalVisualStudio10Generator.h"
+#include "cmLocalVisualStudio7Generator.h"
+#include "cmLocalVisualStudioGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPropertyMap.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
+#include "cmSourceGroup.h"
+#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmValue.h"
#include "cmVisualStudioGeneratorOptions.h"
+struct cmIDEFlagTable;
+
static void ConvertToWindowsSlash(std::string& s);
static std::string cmVS10EscapeXML(std::string arg)
@@ -212,14 +235,27 @@ static bool cmVS10IsTargetsFile(std::string const& path)
return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0;
}
-static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
+static VsProjectType computeProjectType(cmGeneratorTarget const* t)
{
- std::string res;
- res = ".vcxproj";
if (t->IsCSharpOnly()) {
- res = ".csproj";
+ return VsProjectType::csproj;
+ }
+ return VsProjectType::vcxproj;
+}
+
+static std::string computeProjectFileExtension(VsProjectType projectType)
+{
+ switch (projectType) {
+ case VsProjectType::csproj:
+ return ".csproj";
+ default:
+ return ".vcxproj";
}
- return res;
+}
+
+static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
+{
+ return computeProjectFileExtension(computeProjectType(t));
}
cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
@@ -267,7 +303,8 @@ std::string cmVisualStudio10TargetGenerator::CalcCondition(
oss << config << "|" << this->Platform;
oss << "'";
// handle special case for 32 bit C# targets
- if (this->ProjectType == csproj && this->Platform == "Win32") {
+ if (this->ProjectType == VsProjectType::csproj &&
+ this->Platform == "Win32") {
oss << " Or ";
oss << "'$(Configuration)|$(Platform)'=='";
oss << config << "|x86";
@@ -315,21 +352,18 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
void cmVisualStudio10TargetGenerator::Generate()
{
+ this->ProjectType = computeProjectType(this->GeneratorTarget);
+ this->Managed = this->ProjectType == VsProjectType::csproj;
const std::string ProjectFileExtension =
- computeProjectFileExtension(this->GeneratorTarget);
- if (ProjectFileExtension == ".vcxproj") {
- this->ProjectType = vcxproj;
- this->Managed = false;
- } else if (ProjectFileExtension == ".csproj") {
- if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
- std::string message = "The C# target \"" +
- this->GeneratorTarget->GetName() +
- "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
- "disabled in future). Make it a SHARED library instead.";
- this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
- }
- this->ProjectType = csproj;
- this->Managed = true;
+ computeProjectFileExtension(this->ProjectType);
+
+ if (this->ProjectType == VsProjectType::csproj &&
+ this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string message = "The C# target \"" +
+ this->GeneratorTarget->GetName() +
+ "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
+ "disabled in future). Make it a SHARED library instead.";
+ this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
}
if (this->Android &&
@@ -381,6 +415,30 @@ void cmVisualStudio10TargetGenerator::Generate()
// Write the encoding header into the file
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
BuildFileStream.write(magic, 3);
+
+ if (this->ProjectType == VsProjectType::csproj &&
+ this->GeneratorTarget->IsDotNetSdkTarget() &&
+ this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VSVersion::VS16) {
+ this->WriteSdkStyleProjectFile(BuildFileStream);
+ } else {
+ this->WriteClassicMsBuildProjectFile(BuildFileStream);
+ }
+
+ if (BuildFileStream.Close()) {
+ this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
+ }
+
+ // The groups are stored in a separate file for VS 10
+ this->WriteGroups();
+
+ // Update cache with project-specific entries.
+ this->UpdateCache();
+}
+
+void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
+ cmGeneratedFileStream& BuildFileStream)
+{
BuildFileStream << "<?xml version=\"1.0\" encoding=\""
<< this->GlobalGenerator->Encoding() << "\"?>";
{
@@ -388,7 +446,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e0.Attribute("DefaultTargets", "Build");
const char* toolsVersion = this->GlobalGenerator->GetToolsVersion();
if (this->GlobalGenerator->GetVersion() ==
- cmGlobalVisualStudioGenerator::VS12 &&
+ cmGlobalVisualStudioGenerator::VSVersion::VS12 &&
this->GlobalGenerator->TargetsWindowsCE()) {
toolsVersion = "4.0";
}
@@ -423,14 +481,27 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("PreferredToolArchitecture", hostArch);
}
- if (this->ProjectType != csproj) {
+ // ALL_BUILD and ZERO_CHECK projects transitively include
+ // Microsoft.Common.CurrentVersion.targets which triggers Target
+ // ResolveNugetPackageAssets when SDK-style targets are in the project.
+ // However, these projects have no nuget packages to reference and the
+ // build fails.
+ // Setting ResolveNugetPackages to false skips this target and the build
+ // succeeds.
+ cm::string_view targetName{ this->GeneratorTarget->GetName() };
+ if (targetName == "ALL_BUILD" ||
+ targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("ResolveNugetPackages", "false");
+ }
+
+ if (this->ProjectType != VsProjectType::csproj) {
this->WriteProjectConfigurations(e0);
}
{
Elem e1(e0, "PropertyGroup");
- e1.Attribute("Label", "Globals");
- e1.Element("ProjectGuid", "{" + this->GUID + "}");
+ this->WriteCommonPropertyGroupGlobals(e1);
if ((this->MSTools || this->Android) &&
this->GeneratorTarget->IsInBuildSystem()) {
@@ -438,16 +509,6 @@ void cmVisualStudio10TargetGenerator::Generate()
this->VerifyNecessaryFiles();
}
- cmValue vsProjectTypes =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
- if (vsProjectTypes) {
- const char* tagName = "ProjectTypes";
- if (this->ProjectType == csproj) {
- tagName = "ProjectTypeGuids";
- }
- e1.Element(tagName, *vsProjectTypes);
- }
-
cmValue vsProjectName =
this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
cmValue vsLocalPath =
@@ -471,24 +532,6 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("WinMDAssembly", "true");
}
- cmValue vsGlobalKeyword =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
- if (!vsGlobalKeyword) {
- if (this->GlobalGenerator->TargetsAndroid()) {
- e1.Element("Keyword", "Android");
- } else {
- e1.Element("Keyword", "Win32Proj");
- }
- } else {
- e1.Element("Keyword", *vsGlobalKeyword);
- }
-
- cmValue vsGlobalRootNamespace =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
- if (vsGlobalRootNamespace) {
- e1.Element("RootNamespace", *vsGlobalRootNamespace);
- }
-
e1.Element("Platform", this->Platform);
cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
e1.Element("ProjectName", projLabel ? projLabel : this->Name);
@@ -507,16 +550,16 @@ void cmVisualStudio10TargetGenerator::Generate()
} else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
"DOTNET_TARGET_FRAMEWORK_VERSION")) {
targetFrameworkVersion = *tfVer;
- } else if (this->ProjectType == csproj) {
+ } else if (this->ProjectType == VsProjectType::csproj) {
targetFrameworkVersion =
this->GlobalGenerator->GetTargetFrameworkVersion();
}
- if (this->ProjectType == vcxproj &&
+ if (this->ProjectType == VsProjectType::vcxproj &&
this->GlobalGenerator->TargetsWindowsCE()) {
e1.Element("EnableRedirectPlatform", "true");
e1.Element("RedirectPlatformValue", this->Platform);
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
if (this->GlobalGenerator->TargetsWindowsCE()) {
// FIXME: These target VS_TARGET_FRAMEWORK* target properties
// are undocumented settings only ever supported for WinCE.
@@ -569,7 +612,7 @@ void cmVisualStudio10TargetGenerator::Generate()
// 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) {
+ cmGlobalVisualStudioGenerator::VSVersion::VS12) {
e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
}
@@ -578,27 +621,9 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("VCTargetsPath", vcTargetsPath);
}
- std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
- for (std::string const& keyIt : keys) {
- static const cm::string_view prefix = "VS_GLOBAL_";
- if (!cmHasPrefix(keyIt, prefix))
- continue;
- cm::string_view globalKey =
- cm::string_view(keyIt).substr(prefix.length());
- // Skip invalid or separately-handled properties.
- if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
- globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
- continue;
- }
- cmValue value = this->GeneratorTarget->GetProperty(keyIt);
- if (!value)
- continue;
- e1.Element(globalKey, *value);
- }
-
if (this->Managed) {
if (this->LocalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS17) {
+ cmGlobalVisualStudioGenerator::VSVersion::VS17) {
e1.Element("ManagedAssembly", "true");
}
std::string outputType;
@@ -643,7 +668,7 @@ void cmVisualStudio10TargetGenerator::Generate()
}
switch (this->ProjectType) {
- case vcxproj: {
+ case VsProjectType::vcxproj: {
std::string const& props =
this->GlobalGenerator->GetPlatformToolsetVersionProps();
if (!props.empty()) {
@@ -651,7 +676,7 @@ void cmVisualStudio10TargetGenerator::Generate()
}
Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
} break;
- case csproj:
+ case VsProjectType::csproj:
Elem(e0, "Import")
.Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
.Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
@@ -660,7 +685,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteProjectConfigurationValues(e0);
- if (this->ProjectType == vcxproj) {
+ if (this->ProjectType == VsProjectType::vcxproj) {
Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
}
{
@@ -706,10 +731,10 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Attribute("Label", "PropertySheets");
std::string props;
switch (this->ProjectType) {
- case vcxproj:
+ case VsProjectType::vcxproj:
props = VS10_CXX_USER_PROPS;
break;
- case csproj:
+ case VsProjectType::csproj:
props = VS10_CSharp_USER_PROPS;
break;
}
@@ -744,10 +769,10 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteProjectReferences(e0);
this->WriteSDKReferences(e0);
switch (this->ProjectType) {
- case vcxproj:
+ case VsProjectType::vcxproj:
Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
break;
- case csproj:
+ case VsProjectType::csproj:
if (this->GlobalGenerator->TargetsWindowsCE()) {
Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS);
} else {
@@ -788,12 +813,13 @@ void cmVisualStudio10TargetGenerator::Generate()
Elem(e1, "Import").Attribute("Project", nasmTargets);
}
}
- if (this->ProjectType == vcxproj && this->HaveCustomCommandDepfile) {
+ if (this->ProjectType == VsProjectType::vcxproj &&
+ this->HaveCustomCommandDepfile) {
std::string depfileTargets =
GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
Elem(e0, "Import").Attribute("Project", depfileTargets);
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
for (std::string const& c : this->Configurations) {
Elem e1(e0, "PropertyGroup");
e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
@@ -814,22 +840,184 @@ void cmVisualStudio10TargetGenerator::Generate()
}
}
}
+}
- if (BuildFileStream.Close()) {
- this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
+void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
+ cmGeneratedFileStream& BuildFileStream)
+{
+ if (this->ProjectType != VsProjectType::csproj ||
+ !this->GeneratorTarget->IsDotNetSdkTarget()) {
+ std::string message = "The target \"" + this->GeneratorTarget->GetName() +
+ "\" is not eligible for .Net SDK style project.";
+ this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message);
+ return;
}
- // The groups are stored in a separate file for VS 10
- this->WriteGroups();
+ if (this->HasCustomCommands()) {
+ std::string message = "The target \"" + this->GeneratorTarget->GetName() +
+ "\" does not currently support add_custom_command as the Visual Studio "
+ "generators have not yet learned how to generate custom commands in "
+ ".Net SDK-style projects.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, message);
+ return;
+ }
+
+ Elem e0(BuildFileStream, "Project");
+ e0.Attribute("Sdk", *this->GeneratorTarget->GetProperty("DOTNET_SDK"));
+
+ {
+ Elem e1(e0, "PropertyGroup");
+ this->WriteCommonPropertyGroupGlobals(e1);
+
+ e1.Element("EnableDefaultItems", "false");
+ // 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.
+ e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
+ e1.Element("ManagedAssembly", "true");
+
+ cmValue targetFramework =
+ this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
+ if (targetFramework) {
+ if (targetFramework->find(';') != std::string::npos) {
+ e1.Element("TargetFrameworks", *targetFramework);
+ } else {
+ e1.Element("TargetFramework", *targetFramework);
+ }
+ } else {
+ e1.Element("TargetFramework", "net5.0");
+ }
+
+ std::string outputType;
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Target \"", this->GeneratorTarget->GetName(),
+ "\" is of a type not supported for managed binaries."));
+ return;
+ case cmStateEnums::SHARED_LIBRARY:
+ outputType = "Library";
+ break;
+ case cmStateEnums::EXECUTABLE: {
+ auto const win32 =
+ this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
+ if (win32.find("$<") != std::string::npos) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Target \"", this->GeneratorTarget->GetName(),
+ "\" has a generator expression in its WIN32_EXECUTABLE "
+ "property. This is not supported on managed "
+ "executables."));
+ return;
+ }
+ outputType = "Exe";
+ } break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ case cmStateEnums::GLOBAL_TARGET:
+ outputType = "Utility";
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ break;
+ }
+ e1.Element("OutputType", outputType);
+ }
+
+ for (const std::string& config : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", "'$(Configuration)' == '" + config + "'");
+ e1.SetHasElements();
+ this->WriteEvents(e1, config);
+
+ std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
+ ConvertToWindowsSlash(outDir);
+ e1.Element("OutputPath", outDir);
+ }
+
+ this->WriteDotNetDocumentationFile(e0);
+ this->WriteAllSources(e0);
+ this->WriteDotNetReferences(e0);
+ this->WritePackageReferences(e0);
+ this->WriteProjectReferences(e0);
}
-void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
+void cmVisualStudio10TargetGenerator::WriteCommonPropertyGroupGlobals(Elem& e1)
{
- std::vector<std::string> packageReferences;
- if (cmValue vsPackageReferences =
- this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) {
- cmExpandList(*vsPackageReferences, packageReferences);
+ e1.Attribute("Label", "Globals");
+ e1.Element("ProjectGuid", "{" + this->GUID + "}");
+
+ cmValue vsProjectTypes =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
+ if (vsProjectTypes) {
+ const char* tagName = "ProjectTypes";
+ if (this->ProjectType == VsProjectType::csproj) {
+ tagName = "ProjectTypeGuids";
+ }
+ e1.Element(tagName, *vsProjectTypes);
}
+
+ cmValue vsGlobalKeyword =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
+ if (!vsGlobalKeyword) {
+ if (this->GlobalGenerator->TargetsAndroid()) {
+ e1.Element("Keyword", "Android");
+ } else {
+ e1.Element("Keyword", "Win32Proj");
+ }
+ } else {
+ e1.Element("Keyword", *vsGlobalKeyword);
+ }
+
+ cmValue vsGlobalRootNamespace =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if (vsGlobalRootNamespace) {
+ e1.Element("RootNamespace", *vsGlobalRootNamespace);
+ }
+
+ std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
+ for (std::string const& keyIt : keys) {
+ static const cm::string_view prefix = "VS_GLOBAL_";
+ if (!cmHasPrefix(keyIt, prefix))
+ continue;
+ cm::string_view globalKey = cm::string_view(keyIt).substr(prefix.length());
+ // Skip invalid or separately-handled properties.
+ if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
+ globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
+ continue;
+ }
+ cmValue value = this->GeneratorTarget->GetProperty(keyIt);
+ if (!value)
+ continue;
+ e1.Element(globalKey, *value);
+ }
+}
+
+bool cmVisualStudio10TargetGenerator::HasCustomCommands() const
+{
+ if (!this->GeneratorTarget->GetPreBuildCommands().empty() ||
+ !this->GeneratorTarget->GetPreLinkCommands().empty() ||
+ !this->GeneratorTarget->GetPostBuildCommands().empty()) {
+ return true;
+ }
+
+ for (cmGeneratorTarget::AllConfigSource const& si :
+ this->GeneratorTarget->GetAllConfigSources()) {
+ if (si.Source->GetCustomCommand()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
+{
+ std::vector<std::string> packageReferences =
+ this->GeneratorTarget->GetPackageReferences();
+
if (!packageReferences.empty()) {
Elem e1(e0, "ItemGroup");
for (std::string const& ri : packageReferences) {
@@ -959,7 +1147,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0)
std::string const& documentationFile =
this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE");
- if (this->ProjectType == csproj && !documentationFile.empty()) {
+ if (this->ProjectType == VsProjectType::csproj &&
+ !documentationFile.empty()) {
Elem e1(e0, "PropertyGroup");
Elem e2(e1, "DocumentationFile");
e2.Content(documentationFile);
@@ -976,7 +1165,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
std::string obj = oi->GetFullPath();
ConvertToWindowsSlash(obj);
bool useRelativePath = false;
- if (this->ProjectType == csproj && this->InSourceBuild) {
+ if (this->ProjectType == VsProjectType::csproj && this->InSourceBuild) {
// If we do an in-source build and the resource file is in a
// subdirectory
// of the .csproj file, we have to use relative pathnames, otherwise
@@ -990,7 +1179,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
Elem e2(e1, "EmbeddedResource");
e2.Attribute("Include", obj);
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
e2.Element("DependentUpon", hFileName);
@@ -1161,7 +1350,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
e1.Attribute("Condition", this->CalcCondition(c));
e1.Attribute("Label", "Configuration");
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
std::string configType;
if (cmValue vsConfigurationType =
this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
@@ -1292,6 +1481,10 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
if (this->IPOEnabledConfigurations.count(config) > 0) {
e1.Element("WholeProgramOptimization", "true");
}
+ if (this->ASanEnabledConfigurations.find(config) !=
+ this->ASanEnabledConfigurations.end()) {
+ e1.Element("EnableAsan", "true");
+ }
{
auto s = this->SpectreMitigation.find(config);
if (s != this->SpectreMitigation.end()) {
@@ -1470,7 +1663,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
std::unique_ptr<Elem> spe1;
std::unique_ptr<Elem> spe2;
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
this->WriteSource(*spe2, source);
@@ -1494,7 +1687,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
std::stringstream additional_inputs;
{
const char* sep = "";
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
// csproj files do not attach the command to a specific file
// so the primary input must be listed explicitly.
additional_inputs << source->GetFullPath();
@@ -1524,7 +1717,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
}
}
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
additional_inputs << sep << "%(AdditionalInputs)";
}
}
@@ -1545,7 +1738,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
}
}
- if (this->ProjectType == csproj) {
+ script += lg->FinishConstructScript(this->ProjectType);
+ if (this->ProjectType == VsProjectType::csproj) {
std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
@@ -1569,13 +1763,13 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
e2.WritePlatformConfigTag("Outputs", cond, outputs);
if (this->LocalGenerator->GetVersion() >
- cmGlobalVisualStudioGenerator::VS10) {
+ cmGlobalVisualStudioGenerator::VSVersion::VS10) {
// VS >= 11 let us turn off linking of custom command outputs.
e2.WritePlatformConfigTag("LinkObjects", cond, "false");
}
if (symbolic &&
this->LocalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS16) {
+ cmGlobalVisualStudioGenerator::VSVersion::VS16) {
// VS >= 16.4 warn if outputs are not created, but one of our
// outputs is marked SYMBOLIC and not expected to be created.
e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
@@ -1636,7 +1830,7 @@ static void ConvertToWindowsSlash(std::string& s)
void cmVisualStudio10TargetGenerator::WriteGroups()
{
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
@@ -1901,7 +2095,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(
std::string includeInVsix;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- if (this->ProjectType == csproj && !this->InSourceBuild) {
+ if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
toolHasSettings = true;
}
if (ext == "hlsl") {
@@ -2138,7 +2332,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
bool forceRelative = sf->GetLanguage() == "CUDA";
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
- cmGlobalVisualStudioGenerator::VS10 &&
+ cmGlobalVisualStudioGenerator::VSVersion::VS10 &&
cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
@@ -2162,7 +2356,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
ConvertToWindowsSlash(sourceFile);
e2.Attribute("Include", sourceFile);
- if (this->ProjectType == csproj && !this->InSourceBuild) {
+ if (this->ProjectType == VsProjectType::csproj && !this->InSourceBuild) {
// For out of source projects we have to provide a link (if not specified
// via property) for every source file (besides .cs files) otherwise they
// will not be visible in VS at all.
@@ -2236,7 +2430,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
case cmGeneratorTarget::SourceKindExternalObject:
tool = "Object";
if (this->LocalGenerator->GetVersion() <
- cmGlobalVisualStudioGenerator::VS11) {
+ cmGlobalVisualStudioGenerator::VSVersion::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
@@ -2348,12 +2542,13 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
// Visual Studio versions prior to 2017 15.8 do not know about unity
// builds, thus we exclude the files already part of unity sources.
if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
- exclude_configs = si.Configs;
+ exclude_configs = all_configs;
}
}
}
- if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
+ if (si.Kind == cmGeneratorTarget::SourceKindObjectSource ||
+ si.Kind == cmGeneratorTarget::SourceKindUnityBatched) {
this->OutputSourceSpecificFlags(e2, si.Source);
}
if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
@@ -2464,6 +2659,22 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
e2.Element("ObjectFileName", "$(IntDir)/" + objectName);
}
}
+
+ if (lang == "ASM_NASM") {
+ if (cmValue objectDeps = sf.GetProperty("OBJECT_DEPENDS")) {
+ std::string dependencies;
+ std::vector<std::string> depends = cmExpandedList(*objectDeps);
+ const char* sep = "";
+ for (std::string& d : depends) {
+ ConvertToWindowsSlash(d);
+ dependencies += sep;
+ dependencies += d;
+ sep = ";";
+ }
+ e2.Element("AdditionalDependencies", dependencies);
+ }
+ }
+
for (std::string const& config : this->Configurations) {
std::string configUpper = cmSystemTools::UpperCase(config);
std::string configDefines = defines;
@@ -2536,11 +2747,15 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
if (needsPCHFlags) {
// Add precompile headers compile options.
- std::string expandedOptions;
- std::string pchOptions;
if (makePCH) {
- pchOptions =
- this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
+ clOptions.AddFlag("PrecompiledHeader", "Create");
+ std::string pchHeader =
+ this->GeneratorTarget->GetPchHeader(config, lang);
+ clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
+ std::string pchFile =
+ this->GeneratorTarget->GetPchFile(config, lang);
+ clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
+ clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
} else if (useNoPCH) {
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
} else if (useSharedPCH) {
@@ -2548,12 +2763,15 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
this->GeneratorTarget->GetPchHeader(config, lang);
clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
} else if (useDifferentLangPCH) {
- pchOptions =
- this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
+ clOptions.AddFlag("PrecompiledHeader", "Use");
+ std::string pchHeader =
+ this->GeneratorTarget->GetPchHeader(config, lang);
+ clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
+ std::string pchFile =
+ this->GeneratorTarget->GetPchFile(config, lang);
+ clOptions.AddFlag("PrecompiledHeaderOutputFile", pchFile);
+ clOptions.AddFlag("ForcedIncludeFiles", pchHeader);
}
- this->LocalGenerator->AppendCompileOptions(expandedOptions,
- pchOptions);
- clOptions.Parse(expandedOptions);
}
if (!options.empty()) {
@@ -2603,7 +2821,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
e2.Element("DependentUpon",
fileName.substr(0, fileName.find_last_of(".")));
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
std::string f = source->GetFullPath();
using CsPropMap = std::map<std::string, std::string>;
CsPropMap sourceFileTags;
@@ -2634,7 +2852,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
if (ttype > cmStateEnums::GLOBAL_TARGET) {
return;
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
@@ -2643,40 +2861,6 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
for (std::string const& config : this->Configurations) {
const std::string cond = this->CalcCondition(config);
- if (ttype <= cmStateEnums::UTILITY) {
- if (cmValue workingDir = this->GeneratorTarget->GetProperty(
- "VS_DEBUGGER_WORKING_DIRECTORY")) {
- std::string genWorkingDir = cmGeneratorExpression::Evaluate(
- *workingDir, this->LocalGenerator, config);
- e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
- genWorkingDir);
- }
-
- if (cmValue environment =
- this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
- std::string genEnvironment = cmGeneratorExpression::Evaluate(
- *environment, this->LocalGenerator, config);
- e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
- genEnvironment);
- }
-
- if (cmValue debuggerCommand =
- this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
- std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
- *debuggerCommand, this->LocalGenerator, config);
- e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
- genDebuggerCommand);
- }
-
- if (cmValue commandArguments = this->GeneratorTarget->GetProperty(
- "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
- std::string genCommandArguments = cmGeneratorExpression::Evaluate(
- *commandArguments, this->LocalGenerator, config);
- e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
- genCommandArguments);
- }
- }
-
if (ttype >= cmStateEnums::UTILITY) {
e1.WritePlatformConfigTag(
"IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
@@ -2753,6 +2937,40 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
this->OutputLinkIncremental(e1, config);
}
+
+ if (ttype <= cmStateEnums::UTILITY) {
+ if (cmValue workingDir = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_WORKING_DIRECTORY")) {
+ std::string genWorkingDir = cmGeneratorExpression::Evaluate(
+ *workingDir, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
+ genWorkingDir);
+ }
+
+ if (cmValue environment =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
+ std::string genEnvironment = cmGeneratorExpression::Evaluate(
+ *environment, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
+ genEnvironment);
+ }
+
+ if (cmValue debuggerCommand =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+ std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
+ *debuggerCommand, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
+ genDebuggerCommand);
+ }
+
+ if (cmValue commandArguments = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
+ std::string genCommandArguments = cmGeneratorExpression::Evaluate(
+ *commandArguments, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
+ genCommandArguments);
+ }
+ }
}
}
@@ -2762,7 +2980,7 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
if (!this->MSTools) {
return;
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
// static libraries and things greater than modules do not need
@@ -2830,11 +3048,11 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
std::unique_ptr<Options> pOptions;
switch (this->ProjectType) {
- case vcxproj:
+ case VsProjectType::vcxproj:
pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::Compiler, gg->GetClFlagTable());
break;
- case csproj:
+ case VsProjectType::csproj:
pOptions =
cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler,
gg->GetCSharpFlagTable());
@@ -2854,7 +3072,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// Choose a language whose flags to use for ClCompile.
static const char* clLangs[] = { "CXX", "C", "Fortran" };
std::string langForClCompile;
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
langForClCompile = "CSharp";
} else if (cm::contains(clLangs, linkLanguage)) {
langForClCompile = linkLanguage;
@@ -2881,12 +3099,18 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->IPOEnabledConfigurations.insert(configName);
}
+ // Check if ASan is enabled.
+ if (flags.find("/fsanitize=address") != std::string::npos) {
+ this->ASanEnabledConfigurations.insert(configName);
+ }
+
// Precompile Headers
std::string pchHeader =
this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
- if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) {
+ if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
+ pchHeader.empty()) {
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
- } else if (this->MSTools && vcxproj == this->ProjectType &&
+ } else if (this->MSTools && VsProjectType::vcxproj == this->ProjectType &&
!pchHeader.empty()) {
clOptions.AddFlag("PrecompiledHeader", "Use");
clOptions.AddFlag("PrecompiledHeaderFile", pchHeader);
@@ -2898,10 +3122,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
- if (this->ProjectType == vcxproj) {
+ if (this->ProjectType == VsProjectType::vcxproj) {
clOptions.FixExceptionHandlingDefault();
if (this->GlobalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS15) {
+ cmGlobalVisualStudioGenerator::VSVersion::VS15) {
// Toolsets that come with VS 2017 may now enable UseFullPaths
// by default and there is no negative /FC option that projects
// can use to switch it back. Older toolsets disable this by
@@ -2916,7 +3140,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// check for managed C++ assembly compiler flag. This overrides any
// /clr* compiler flags which may be defined in the flags variable(s).
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
// Warn if /clr was added manually. This should not be done
// anymore, because cmGeneratorTarget may not be aware that the
// target uses C++/CLI.
@@ -2945,13 +3169,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.Parse(defineFlags);
std::vector<std::string> targetDefines;
switch (this->ProjectType) {
- case vcxproj:
+ case VsProjectType::vcxproj:
if (!langForClCompile.empty()) {
this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
langForClCompile);
}
break;
- case csproj:
+ case VsProjectType::csproj:
this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
"CSharp");
cm::erase_if(targetDefines, [](std::string const& def) {
@@ -2961,7 +3185,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
clOptions.AddDefines(targetDefines);
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
clOptions.AppendFlag("DefineConstants", targetDefines);
}
@@ -3024,7 +3248,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
}
- if (this->ProjectType != csproj && clOptions.IsManaged()) {
+ if (this->ProjectType != VsProjectType::csproj && clOptions.IsManaged()) {
this->Managed = true;
std::string managedType = clOptions.GetFlag("CompileAsManaged");
if (managedType == "Safe" || managedType == "Pure") {
@@ -3037,7 +3261,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.AddFlag("ExceptionHandling", "Async");
clOptions.AddFlag("BasicRuntimeChecks", "Default");
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
// /nowin32manifest overrides /win32manifest: parameter
if (clOptions.HasFlag("NoWin32Manifest")) {
clOptions.RemoveFlag("ApplicationManifest");
@@ -3063,7 +3287,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
Elem& e1, std::string const& configName)
{
Options& clOptions = *(this->ClOptions[configName]);
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
Elem e2(e1, "ClCompile");
@@ -3201,6 +3425,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaOptions = *pOptions;
+ auto cudaVersion = this->GlobalGenerator->GetPlatformToolsetCudaString();
+
// Get compile flags for CUDA in this directory.
std::string flags;
this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, "CUDA",
@@ -3226,16 +3452,30 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
// the default to not have any extension
cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).obj");
- bool notPtx = true;
if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
- } else if (this->GeneratorTarget->GetPropertyAsBool(
- "CUDA_PTX_COMPILATION")) {
+ }
+ bool notPtx = true;
+ 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");
notPtx = false;
+
+ if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
+ cudaVersion, "9.0") &&
+ cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, cudaVersion,
+ "11.5")) {
+ // The DriverApi flag before 11.5 ( verified back to 9.0 ) which controls
+ // PTX compilation doesn't propagate user defines causing
+ // target_compile_definitions to behave differently for VS +
+ // PTX compared to other generators so we patch the rules
+ // to normalize behavior
+ cudaOptions.AddFlag("DriverApiCommandLineTemplate",
+ "%(BaseCommandLineTemplate) [CompileOut] [FastMath] "
+ "[Defines] \"%(FullPath)\"");
+ }
}
if (notPtx &&
@@ -4014,7 +4254,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
@@ -4050,7 +4290,7 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
if (!location.empty()) {
ConvertToWindowsSlash(location);
switch (this->ProjectType) {
- case csproj:
+ case VsProjectType::csproj:
// If the target we want to "link" to is an imported managed
// target and this is a C# project, we add a hint reference. This
// reference is written to project file in
@@ -4058,7 +4298,7 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
this->DotNetHintReferences[config].push_back(
DotNetHintReference(l.Target->GetName(), location));
break;
- case vcxproj:
+ case VsProjectType::vcxproj:
// Add path of assembly to list of using-directories, so the
// managed assembly can be used by '#using <assembly.dll>' in
// code.
@@ -4118,7 +4358,7 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
if (!this->MSTools) {
return;
}
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
@@ -4159,7 +4399,7 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
{
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
return;
}
for (const std::string& c : this->Configurations) {
@@ -4178,7 +4418,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
// output midl flags <Midl></Midl>
this->WriteMidlOptions(e1, c);
// write events
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
this->WriteEvents(e1, c);
}
// output link flags <Link></Link>
@@ -4243,8 +4483,11 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
}
}
+ if (!script.empty()) {
+ script += lg->FinishConstructScript(this->ProjectType);
+ }
comment = cmVS10EscapeComment(comment);
- if (this->ProjectType != csproj) {
+ if (this->ProjectType != VsProjectType::csproj) {
Elem e2(e1, name);
if (stdPipesUTF8) {
this->WriteStdOutEncodingUtf8(e2);
@@ -5066,7 +5309,7 @@ bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
cmSourceFile const* sf, std::map<std::string, std::string>& tags)
{
- if (this->ProjectType == csproj) {
+ if (this->ProjectType == VsProjectType::csproj) {
const cmPropertyMap& props = sf->GetProperties();
for (const std::string& p : props.GetKeys()) {
static const cm::string_view propNamePrefix = "VS_CSHARP_";
@@ -5152,3 +5395,32 @@ void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1)
e1.Element("StdOutEncoding", "UTF-8");
}
}
+
+void cmVisualStudio10TargetGenerator::UpdateCache()
+{
+ std::vector<std::string> packageReferences;
+
+ if (this->GeneratorTarget->HasPackageReferences()) {
+ // Store a cache entry that later determines, if a package restore is
+ // required.
+ this->GeneratorTarget->Makefile->AddCacheDefinition(
+ this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE", "ON",
+ "Value Computed by CMake", cmStateEnums::STATIC);
+ } else {
+ // If there are any dependencies that require package restore, inherit the
+ // cache variable.
+ cmGlobalGenerator::TargetDependSet const& unordered =
+ this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
+ using OrderedTargetDependSet =
+ cmGlobalVisualStudioGenerator::OrderedTargetDependSet;
+ OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+
+ for (cmGeneratorTarget const* dt : depends) {
+ if (dt->HasPackageReferences()) {
+ this->GeneratorTarget->Makefile->AddCacheDefinition(
+ this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE",
+ "ON", "Value Computed by CMake", cmStateEnums::STATIC);
+ }
+ }
+ }
+}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index a5ce5e5..8d777a3 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -4,15 +4,17 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <iosfwd>
+#include <cstddef>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
+#include <utility>
#include <vector>
#include "cmGeneratorTarget.h"
+#include "cmVsProjectType.h"
class cmComputeLinkInformation;
class cmCustomCommand;
@@ -196,6 +198,7 @@ private:
std::string GetCSharpSourceLink(cmSourceFile const* source);
void WriteStdOutEncodingUtf8(Elem& e1);
+ void UpdateCache();
private:
friend class cmVS10GeneratorOptions;
@@ -209,11 +212,8 @@ private:
OptionsMap NasmOptions;
OptionsMap LinkOptions;
std::string LangForClCompile;
- enum VsProjectType
- {
- vcxproj,
- csproj
- } ProjectType;
+
+ VsProjectType ProjectType;
bool InSourceBuild;
std::vector<std::string> Configurations;
std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
@@ -230,6 +230,7 @@ private:
unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
std::set<std::string> IPOEnabledConfigurations;
+ std::set<std::string> ASanEnabledConfigurations;
std::map<std::string, std::string> SpectreMitigation;
cmGlobalVisualStudio10Generator* const GlobalGenerator;
cmLocalVisualStudio10Generator* const LocalGenerator;
@@ -259,6 +260,15 @@ private:
void ClassifyAllConfigSources();
void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs);
+ // .Net SDK-stype project variable and helper functions
+ void WriteClassicMsBuildProjectFile(cmGeneratedFileStream& BuildFileStream);
+ void WriteSdkStyleProjectFile(cmGeneratedFileStream& BuildFileStream);
+
+ void WriteCommonPropertyGroupGlobals(
+ cmVisualStudio10TargetGenerator::Elem& e1);
+
+ bool HasCustomCommands() const;
+
std::unordered_map<std::string, ConfigToSettings> ParsedToolTargetSettings;
bool PropertyIsSameInAllConfigs(const ConfigToSettings& toolSettings,
const std::string& propName);
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 058ffb4..9045a4d 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -1,12 +1,18 @@
#include "cmVisualStudioGeneratorOptions.h"
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <utility>
+#include <vector>
+
#include <cm/iterator>
#include "cmAlgorithms.h"
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudioGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
static void cmVS10EscapeForMSBuild(std::string& ret)
@@ -69,13 +75,13 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
// 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 cmGlobalVisualStudioGenerator::VS10:
- case cmGlobalVisualStudioGenerator::VS11:
- case cmGlobalVisualStudioGenerator::VS12:
- case cmGlobalVisualStudioGenerator::VS14:
- case cmGlobalVisualStudioGenerator::VS15:
- case cmGlobalVisualStudioGenerator::VS16:
- case cmGlobalVisualStudioGenerator::VS17:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS10:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS11:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS12:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS14:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS15:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS16:
+ case cmGlobalVisualStudioGenerator::VSVersion::VS17:
// 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
@@ -102,7 +108,8 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
if (verbose &&
this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end()) {
this->FlagMap["SuppressStartupBanner"] =
- this->Version < cmGlobalVisualStudioGenerator::VS10 ? "FALSE" : "";
+ this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10 ? "FALSE"
+ : "";
}
}
@@ -175,6 +182,10 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// First entries for the -arch=<arch> [-code=<code>,...] pair.
if (!arch.empty()) {
std::string arch_name = arch[0];
+ if (arch_name == "all" || arch_name == "all-major") {
+ AppendFlagString("AdditionalOptions", "-arch=" + arch_name);
+ return;
+ }
std::vector<std::string> codes;
if (!code.empty()) {
codes = cmTokenize(code[0], ",");
@@ -419,7 +430,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
std::ostringstream oss;
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
oss << "%(" << tag << ")";
}
std::vector<std::string>::const_iterator de =
@@ -427,13 +438,13 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) {
// Escape the definition for the compiler.
std::string define;
- if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10) {
define = this->LocalGenerator->EscapeForShell(di, true);
} else {
define = di;
}
// Escape this flag for the MSBuild.
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
cmVS10EscapeForMSBuild(define);
if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
@@ -475,7 +486,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
}
// Escape this include for the MSBuild.
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
cmVS10EscapeForMSBuild(include);
}
oss << sep << include;
@@ -487,7 +498,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
}
}
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
oss << sep << "%(" << tag << ")";
}
@@ -501,7 +512,7 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
std::ostringstream oss;
const char* sep = "";
for (std::string i : m.second) {
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) {
cmVS10EscapeForMSBuild(i);
}
oss << sep << i;
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index b123019..ed4ee1d 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -12,7 +12,6 @@
#include "cmIDEOptions.h"
class cmLocalVisualStudioGenerator;
-class cmGeneratorTarget;
using cmVS7FlagTable = cmIDEFlagTable;
diff --git a/Source/cmVisualStudioSlnData.cxx b/Source/cmVisualStudioSlnData.cxx
index 48112dd..2a6dfc4 100644
--- a/Source/cmVisualStudioSlnData.cxx
+++ b/Source/cmVisualStudioSlnData.cxx
@@ -2,24 +2,42 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudioSlnData.h"
-const cmSlnProjectEntry* cmSlnData::GetProjectByGUID(
+#include <cstddef>
+#include <utility>
+
+#include "cmSystemTools.h"
+
+void cmSlnProjectEntry::AddProjectConfiguration(
+ const std::string& solutionConfiguration,
+ const std::string& projectConfiguration)
+{
+ projectConfigurationMap[solutionConfiguration] = projectConfiguration;
+}
+
+std::string cmSlnProjectEntry::GetProjectConfiguration(
+ const std::string& solutionConfiguration)
+{
+ return projectConfigurationMap[solutionConfiguration];
+}
+
+const cm::optional<cmSlnProjectEntry> cmSlnData::GetProjectByGUID(
const std::string& projectGUID) const
{
ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID));
if (it != ProjectsByGUID.end())
- return &it->second;
+ return it->second;
else
- return NULL;
+ return cm::nullopt;
}
-const cmSlnProjectEntry* cmSlnData::GetProjectByName(
+const cm::optional<cmSlnProjectEntry> cmSlnData::GetProjectByName(
const std::string& projectName) const
{
ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName));
if (it != ProjectNameIndex.end())
- return &it->second->second;
+ return it->second->second;
else
- return NULL;
+ return cm::nullopt;
}
std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const
@@ -47,3 +65,24 @@ cmSlnProjectEntry* cmSlnData::AddProject(
ProjectNameIndex[projectName] = it;
return &it->second;
}
+
+std::string cmSlnData::GetConfigurationTarget(
+ const std::string& projectName, const std::string& solutionConfiguration,
+ const std::string& platformName)
+{
+ std::string solutionTarget = solutionConfiguration + "|" + platformName;
+ cm::optional<cmSlnProjectEntry> project = GetProjectByName(projectName);
+ if (!project)
+ return platformName;
+
+ std::string projectTarget = project->GetProjectConfiguration(solutionTarget);
+ if (projectTarget.empty())
+ return platformName;
+
+ std::vector<std::string> targetElements =
+ cmSystemTools::SplitString(projectTarget, '|');
+ if (targetElements.size() != 2)
+ return platformName;
+
+ return targetElements[1];
+}
diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h
index b217bd8..100dd9b 100644
--- a/Source/cmVisualStudioSlnData.h
+++ b/Source/cmVisualStudioSlnData.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
class cmSlnProjectEntry
{
public:
@@ -24,17 +26,40 @@ public:
std::string GetName() const { return Name; }
std::string GetRelativePath() const { return RelativePath; }
+ void AddProjectConfiguration(const std::string& solutionConfiguration,
+ const std::string& projectConfiguration);
+
+ std::string GetProjectConfiguration(
+ const std::string& solutionConfiguration);
+
private:
std::string Guid, Name, RelativePath;
+ std::map<std::string, std::string> projectConfigurationMap;
};
class cmSlnData
{
public:
- const cmSlnProjectEntry* GetProjectByGUID(
+ std::string GetVisualStudioVersion() const { return visualStudioVersion; }
+ void SetVisualStudioVersion(const std::string& version)
+ {
+ visualStudioVersion = version;
+ }
+
+ std::string GetMinimumVisualStudioVersion() const
+ {
+ return minimumVisualStudioVersion;
+ }
+
+ void SetMinimumVisualStudioVersion(const std::string& version)
+ {
+ minimumVisualStudioVersion = version;
+ }
+
+ const cm::optional<cmSlnProjectEntry> GetProjectByGUID(
const std::string& projectGUID) const;
- const cmSlnProjectEntry* GetProjectByName(
+ const cm::optional<cmSlnProjectEntry> GetProjectByName(
const std::string& projectName) const;
std::vector<cmSlnProjectEntry> GetProjects() const;
@@ -43,9 +68,20 @@ public:
const std::string& projectName,
const std::string& projectRelativePath);
+ void AddConfiguration(const std::string& configuration)
+ {
+ solutionConfigurations.push_back(configuration);
+ }
+
+ std::string GetConfigurationTarget(const std::string& projectName,
+ const std::string& solutionConfiguration,
+ const std::string& platformName);
+
private:
+ std::string visualStudioVersion, minimumVisualStudioVersion;
using ProjectStorage = std::map<std::string, cmSlnProjectEntry>;
ProjectStorage ProjectsByGUID;
using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>;
ProjectStringIndex ProjectNameIndex;
+ std::vector<std::string> solutionConfigurations;
};
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index d7822b1..feab895 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -3,7 +3,10 @@
#include "cmVisualStudioSlnParser.h"
#include <cassert>
+#include <memory>
#include <stack>
+#include <utility>
+#include <vector>
#include "cmsys/FStream.hxx"
@@ -217,9 +220,14 @@ bool cmVisualStudioSlnParser::State::Process(
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 if (line.GetTag().compare("VisualStudioVersion") == 0) {
+ output.SetVisualStudioVersion(line.GetValue(0));
+ } else if (line.GetTag().compare("MinimumVisualStudioVersion") == 0) {
+ output.SetMinimumVisualStudioVersion(line.GetValue(0));
+ } else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
}
@@ -287,10 +295,9 @@ bool cmVisualStudioSlnParser::State::Process(
case FileStateSolutionConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0)
this->Stack.pop();
- else if (line.IsKeyValuePair())
- // implement configuration storing here, once needed
- ;
- else {
+ else if (line.IsKeyValuePair()) {
+ output.AddConfiguration(line.GetValue(0));
+ } else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
}
@@ -298,10 +305,30 @@ bool cmVisualStudioSlnParser::State::Process(
case FileStateProjectConfigurations:
if (line.GetTag().compare("EndGlobalSection") == 0)
this->Stack.pop();
- else if (line.IsKeyValuePair())
- // implement configuration storing here, once needed
- ;
- else {
+ else if (line.IsKeyValuePair()) {
+ std::vector<std::string> tagElements =
+ cmSystemTools::SplitString(line.GetTag(), '.');
+ if (tagElements.size() != 3 && tagElements.size() != 4) {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+
+ std::string guid = tagElements[0];
+ std::string solutionConfiguration = tagElements[1];
+ std::string activeBuild = tagElements[2];
+ cm::optional<cmSlnProjectEntry> projectEntry =
+ output.GetProjectByGUID(guid);
+
+ if (!projectEntry) {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+
+ if (activeBuild.compare("ActiveCfg") == 0) {
+ projectEntry->AddProjectConfiguration(solutionConfiguration,
+ line.GetValue(0));
+ }
+ } else {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
}
@@ -452,8 +479,7 @@ bool cmVisualStudioSlnParser::GetParseHadBOM() const
bool cmVisualStudioSlnParser::IsDataGroupSetSupported(
DataGroupSet dataGroups) const
{
- return (dataGroups & DataGroupProjects) == dataGroups;
- // only supporting DataGroupProjects for now
+ return (dataGroups & DataGroupProjects) != 0;
}
bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,
diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h
index 1c33759..60be598 100644
--- a/Source/cmVisualStudioSlnParser.h
+++ b/Source/cmVisualStudioSlnParser.h
@@ -5,13 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <bitset>
+#include <cstddef>
#include <iosfwd>
#include <string>
#include <cm/string_view>
-#include <stddef.h>
-
class cmSlnData;
class cmVisualStudioSlnParser
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
index 3b113aa..2f71cf5 100644
--- a/Source/cmVisualStudioWCEPlatformParser.cxx
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudioWCEPlatformParser.h"
+#include <algorithm>
+#include <cstring>
+#include <utility>
+
#include "cmGlobalVisualStudioGenerator.h"
-#include "cmXMLParser.h"
+#include "cmSystemTools.h"
int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
{
diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h
index eb4e978..2fff91c 100644
--- a/Source/cmVisualStudioWCEPlatformParser.h
+++ b/Source/cmVisualStudioWCEPlatformParser.h
@@ -4,12 +4,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <map>
#include <string>
#include <vector>
-#include <stddef.h>
-
#include "cmXMLParser.h"
// This class is used to parse XML with configuration
diff --git a/Source/cmVsProjectType.h b/Source/cmVsProjectType.h
new file mode 100644
index 0000000..8899267
--- /dev/null
+++ b/Source/cmVsProjectType.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+enum class VsProjectType
+{
+ vcxproj,
+ csproj
+};
diff --git a/Source/cmXCOFF.cxx b/Source/cmXCOFF.cxx
index 890636e..a6d278d 100644
--- a/Source/cmXCOFF.cxx
+++ b/Source/cmXCOFF.cxx
@@ -61,20 +61,20 @@ namespace {
struct XCOFF32
{
- typedef struct filehdr filehdr;
- typedef struct aouthdr aouthdr;
- typedef struct scnhdr scnhdr;
- typedef struct ldhdr ldhdr;
+ using filehdr = struct filehdr;
+ using aouthdr = struct aouthdr;
+ using scnhdr = struct scnhdr;
+ using ldhdr = struct ldhdr;
static const std::size_t aouthdr_size = _AOUTHSZ_EXEC;
};
const unsigned char xcoff32_magic[] = { 0x01, 0xDF };
struct XCOFF64
{
- typedef struct filehdr_64 filehdr;
- typedef struct aouthdr_64 aouthdr;
- typedef struct scnhdr_64 scnhdr;
- typedef struct ldhdr_64 ldhdr;
+ using filehdr = struct filehdr_64;
+ using aouthdr = struct aouthdr_64;
+ using scnhdr = struct scnhdr_64;
+ using ldhdr = struct ldhdr_64;
static const std::size_t aouthdr_size = _AOUTHSZ_EXEC_64;
};
const unsigned char xcoff64_magic[] = { 0x01, 0xF7 };
@@ -326,8 +326,8 @@ cmXCOFF::cmXCOFF(const char* fname, Mode mode)
cmXCOFF::~cmXCOFF() = default;
-cmXCOFF::cmXCOFF(cmXCOFF&&) = default;
-cmXCOFF& cmXCOFF::operator=(cmXCOFF&&) = default;
+cmXCOFF::cmXCOFF(cmXCOFF&&) noexcept = default;
+cmXCOFF& cmXCOFF::operator=(cmXCOFF&&) noexcept = default;
bool cmXCOFF::Valid() const
{
diff --git a/Source/cmXCOFF.h b/Source/cmXCOFF.h
index 16cda9d..f6d9d94 100644
--- a/Source/cmXCOFF.h
+++ b/Source/cmXCOFF.h
@@ -35,9 +35,9 @@ public:
/** Destruct. */
~cmXCOFF();
- cmXCOFF(cmXCOFF&&);
+ cmXCOFF(cmXCOFF&&) noexcept;
cmXCOFF(cmXCOFF const&) = delete;
- cmXCOFF& operator=(cmXCOFF&&);
+ cmXCOFF& operator=(cmXCOFF&&) noexcept;
cmXCOFF& operator=(cmXCOFF const&) = delete;
/** Get the error message if any. */
diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h
index f3fc438..0c7f22b 100644
--- a/Source/cmXCode21Object.h
+++ b/Source/cmXCode21Object.h
@@ -6,6 +6,7 @@
#include <iosfwd>
#include <memory>
+#include <string>
#include <vector>
#include "cmXCodeObject.h"
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index d5c5275..c817980 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -6,8 +6,6 @@
#include <CoreFoundation/CoreFoundation.h>
-#include "cmSystemTools.h"
-
const char* cmXCodeObject::PBXTypeNames[] = {
/* clang-format needs this comment to break after the opening brace */
"PBXGroup",
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index dd5e86e..389fb62 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <algorithm>
+#include <cstddef>
#include <iosfwd>
#include <map>
#include <string>
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index e2c0f2d..adc500a 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -3,16 +3,24 @@
#include "cmXCodeScheme.h"
#include <iomanip>
-#include <iostream>
#include <sstream>
#include <utility>
#include <cmext/algorithm>
+#include "cmsys/String.h"
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
-#include "cmXMLSafe.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmValue.h"
+#include "cmXCodeObject.h"
+#include "cmXMLWriter.h"
+
+class cmLocalGenerator;
cmXCodeScheme::cmXCodeScheme(cmLocalGenerator* lg, cmXCodeObject* xcObj,
TestObjects tests,
@@ -148,6 +156,16 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
true);
xout.Attribute("debugServiceExtension", "internal");
xout.Attribute("allowLocationSimulation", "YES");
+ if (cmValue gpuFrameCaptureMode = this->Target->GetTarget()->GetProperty(
+ "XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE")) {
+ std::string value = *gpuFrameCaptureMode;
+ if (cmsysString_strcasecmp(value.c_str(), "Metal") == 0) {
+ value = "1";
+ } else if (cmsysString_strcasecmp(value.c_str(), "Disabled") == 0) {
+ value = "3";
+ }
+ xout.Attribute("enableGPUFrameCaptureMode", value);
+ }
// Diagnostics tab begin
diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h
index 11f043e..07fdedb 100644
--- a/Source/cmXCodeScheme.h
+++ b/Source/cmXCodeScheme.h
@@ -4,12 +4,13 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <iosfwd>
+#include <string>
#include <vector>
-#include "cmGlobalXCodeGenerator.h"
-#include "cmSystemTools.h"
-#include "cmXCodeObject.h"
-#include "cmXMLWriter.h"
+class cmLocalGenerator;
+class cmXCodeObject;
+class cmXMLWriter;
/** \class cmXCodeScheme
* \brief Write shared schemes for native targets in Xcode project.
diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h
index 7e805d7..176252d 100644
--- a/Source/cmXMLParser.h
+++ b/Source/cmXMLParser.h
@@ -21,6 +21,7 @@ class cmXMLParser
{
public:
cmXMLParser();
+ cmXMLParser(const cmXMLParser& /*other*/) = default;
virtual ~cmXMLParser();
//! Parse given XML string
diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx
index d31a239..4014635 100644
--- a/Source/cmXMLSafe.cxx
+++ b/Source/cmXMLSafe.cxx
@@ -73,7 +73,7 @@ std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self)
} else {
// Use a human-readable hex value for this invalid character.
char buf[16];
- sprintf(buf, "%X", ch);
+ snprintf(buf, sizeof(buf), "%X", ch);
os << "[NON-XML-CHAR-0x" << buf << "]";
}
@@ -82,7 +82,7 @@ std::ostream& operator<<(std::ostream& os, cmXMLSafe const& self)
ch = static_cast<unsigned char>(*first++);
// Use a human-readable hex value for this invalid byte.
char buf[16];
- sprintf(buf, "%X", ch);
+ snprintf(buf, sizeof(buf), "%X", ch);
os << "[NON-UTF-8-BYTE-0x" << buf << "]";
}
}
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index 216d3f0..8115306 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -3,17 +3,14 @@
#include "cm_codecvt.hxx"
#if defined(_WIN32)
-# include <windows.h>
+# include <cassert>
+# include <cstring>
-# 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];
+# include "cm_utf8.h"
#endif
codecvt::codecvt(Encoding e)
@@ -42,7 +39,7 @@ codecvt::codecvt(Encoding e)
codecvt::~codecvt() = default;
-bool codecvt::do_always_noconv() const throw()
+bool codecvt::do_always_noconv() const noexcept
{
return this->m_noconv;
}
@@ -234,12 +231,12 @@ void codecvt::BufferPartial(mbstate_t& state, int size,
}
#endif
-int codecvt::do_max_length() const throw()
+int codecvt::do_max_length() const noexcept
{
return 4;
}
-int codecvt::do_encoding() const throw()
+int codecvt::do_encoding() const noexcept
{
return 0;
}
diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx
index b73204f..9af083f 100644
--- a/Source/cm_codecvt.hxx
+++ b/Source/cm_codecvt.hxx
@@ -24,14 +24,14 @@ public:
protected:
~codecvt() override;
- bool do_always_noconv() const throw() override;
+ bool do_always_noconv() const noexcept 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 override;
result do_unshift(mbstate_t& state, char* to, char*,
char*& to_next) const override;
- int do_max_length() const throw() override;
- int do_encoding() const throw() override;
+ int do_max_length() const noexcept override;
+ int do_encoding() const noexcept override;
private:
// The mbstate_t argument to do_out and do_unshift is responsible
diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c
index 62e7e8c..b046aef 100644
--- a/Source/cm_utf8.c
+++ b/Source/cm_utf8.c
@@ -42,6 +42,11 @@ static unsigned int const cm_utf8_min[7] = {
const char* cm_utf8_decode_character(const char* first, const char* last,
unsigned int* pc)
{
+ /* We need at least one byte. */
+ if (first == last) {
+ return 0;
+ }
+
/* Count leading ones in the first byte. */
unsigned char c = (unsigned char)*first++;
unsigned char const ones = cm_utf8_ones[c];
diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h
index fa9ed3a..67f3d3f 100644
--- a/Source/cm_utf8.h
+++ b/Source/cm_utf8.h
@@ -6,6 +6,8 @@
extern "C" {
#endif
+extern unsigned char const cm_utf8_ones[256];
+
/** Decode one UTF-8 character from the input byte range. On success,
stores the unicode character number in *pc and returns the first
position not extracted. On failure, returns 0. */
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index fda7900..f9e2d6e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -28,8 +28,9 @@
#include "cm_sys_stat.h"
+#include "cmBuildOptions.h"
#include "cmCMakePath.h"
-#include "cmCMakePresetsFile.h"
+#include "cmCMakePresetsGraph.h"
#include "cmCommandLineArgument.h"
#include "cmCommands.h"
#include "cmDocumentation.h"
@@ -205,7 +206,7 @@ cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind)
exts.ordered.reserve(extList.size());
for (cm::string_view ext : extList) {
exts.ordered.emplace_back(ext);
- };
+ }
// Fill unordered set
exts.unordered.insert(exts.ordered.begin(), exts.ordered.end());
};
@@ -543,6 +544,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
"-C", "-C must be followed by a file name.",
CommandArgument::Values::One, CommandArgument::RequiresSeparator::No,
[&](std::string const& value, cmake* state) -> bool {
+ if (value.empty()) {
+ cmSystemTools::Error("No file name specified for -C");
+ return false;
+ }
cmSystemTools::Stdout("loading initial cache file " + value + "\n");
// Resolve script path specified on command line
// relative to $PWD.
@@ -790,6 +795,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
bool haveBArg = false;
bool scriptMode = false;
std::string possibleUnknownArg;
+ std::string extraProvidedPath;
#if !defined(CMAKE_BOOTSTRAP)
std::string profilingFormat;
std::string profilingOutput;
@@ -798,14 +804,30 @@ void cmake::SetArgs(const std::vector<std::string>& args)
ListPresets listPresets = ListPresets::None;
#endif
+ auto EmptyStringArgLambda = [](std::string const&, cmake* state) -> bool {
+ state->IssueMessage(
+ MessageType::WARNING,
+ "Ignoring empty string (\"\") provided on the command line.");
+ return true;
+ };
+
auto SourceArgLambda = [](std::string const& value, cmake* state) -> bool {
+ if (value.empty()) {
+ cmSystemTools::Error("No source directory specified for -S");
+ return false;
+ }
std::string path = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(path);
- state->SetHomeDirectory(path);
+
+ state->SetHomeDirectoryViaCommandLine(path, HomeDirArgStyle::Dash_S);
return true;
};
auto BuildArgLambda = [&](std::string const& value, cmake* state) -> bool {
+ if (value.empty()) {
+ cmSystemTools::Error("No build directory specified for -B");
+ return false;
+ }
std::string path = cmSystemTools::CollapseFullPath(value);
cmSystemTools::ConvertToUnixSlashes(path);
state->SetHomeOutputDirectory(path);
@@ -834,6 +856,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
};
std::vector<CommandArgument> arguments = {
+ CommandArgument{ "", CommandArgument::Values::Zero, EmptyStringArgLambda },
CommandArgument{ "-S", "No source directory specified for -S",
CommandArgument::Values::One,
CommandArgument::RequiresSeparator::No, SourceArgLambda },
@@ -968,7 +991,34 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"--debug-find", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
std::cout << "Running with debug output on for the `find` commands.\n";
- state->SetDebugFindOutputOn(true);
+ state->SetDebugFindOutput(true);
+ return true;
+ } },
+ CommandArgument{
+ "--debug-find-pkg", "Provide a package argument for --debug-find-pkg",
+ CommandArgument::Values::One, CommandArgument::RequiresSeparator::Yes,
+ [](std::string const& value, cmake* state) -> bool {
+ std::vector<std::string> find_pkgs(cmTokenize(value, ","));
+ std::cout << "Running with debug output on for the 'find' commands "
+ "for package(s)";
+ for (auto const& v : find_pkgs) {
+ std::cout << " " << v;
+ state->SetDebugFindOutputPkgs(v);
+ }
+ std::cout << ".\n";
+ return true;
+ } },
+ CommandArgument{
+ "--debug-find-var", CommandArgument::Values::One,
+ CommandArgument::RequiresSeparator::Yes,
+ [](std::string const& value, cmake* state) -> bool {
+ std::vector<std::string> find_vars(cmTokenize(value, ","));
+ std::cout << "Running with debug output on for the variable(s)";
+ for (auto const& v : find_vars) {
+ std::cout << " " << v;
+ state->SetDebugFindOutputVars(v);
+ }
+ std::cout << ".\n";
return true;
} },
CommandArgument{ "--trace-expand", CommandArgument::Values::Zero,
@@ -1141,10 +1191,18 @@ void cmake::SetArgs(const std::vector<std::string>& args)
} else if (!matched && cmHasLiteralPrefix(arg, "-")) {
possibleUnknownArg = arg;
} else if (!matched) {
- this->SetDirectoriesFromFile(arg);
+ bool parsedDirectory = this->SetDirectoriesFromFile(arg);
+ if (!parsedDirectory) {
+ extraProvidedPath = arg;
+ }
}
}
+ if (!extraProvidedPath.empty() && !scriptMode) {
+ this->IssueMessage(MessageType::WARNING,
+ cmStrCat("Ignoring extra path from command line:\n \"",
+ extraProvidedPath, "\""));
+ }
if (!possibleUnknownArg.empty() && !scriptMode) {
cmSystemTools::Error(cmStrCat("Unknown argument ", possibleUnknownArg));
cmSystemTools::Error("Run 'cmake --help' for all supported options.");
@@ -1212,43 +1270,43 @@ void cmake::SetArgs(const std::vector<std::string>& args)
#if !defined(CMAKE_BOOTSTRAP)
if (listPresets != ListPresets::None || !presetName.empty()) {
- cmCMakePresetsFile settingsFile;
- auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
- if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ cmCMakePresetsGraph presetsGraph;
+ auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory());
+ if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
cmSystemTools::Error(
cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
- ": ", cmCMakePresetsFile::ResultToString(result)));
+ ": ", cmCMakePresetsGraph::ResultToString(result)));
return;
}
if (listPresets != ListPresets::None) {
if (listPresets == ListPresets::Configure) {
- this->PrintPresetList(settingsFile);
+ this->PrintPresetList(presetsGraph);
} else if (listPresets == ListPresets::Build) {
- settingsFile.PrintBuildPresetList();
+ presetsGraph.PrintBuildPresetList();
} else if (listPresets == ListPresets::Test) {
- settingsFile.PrintTestPresetList();
+ presetsGraph.PrintTestPresetList();
} else if (listPresets == ListPresets::All) {
- settingsFile.PrintAllPresets();
+ presetsGraph.PrintAllPresets();
}
this->SetWorkingMode(WorkingMode::HELP_MODE);
return;
}
- auto preset = settingsFile.ConfigurePresets.find(presetName);
- if (preset == settingsFile.ConfigurePresets.end()) {
+ auto preset = presetsGraph.ConfigurePresets.find(presetName);
+ if (preset == presetsGraph.ConfigurePresets.end()) {
cmSystemTools::Error(cmStrCat("No such preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
- this->PrintPresetList(settingsFile);
+ this->PrintPresetList(presetsGraph);
return;
}
if (preset->second.Unexpanded.Hidden) {
cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
this->GetHomeDirectory(), ": \"",
presetName, '"'));
- this->PrintPresetList(settingsFile);
+ this->PrintPresetList(presetsGraph);
return;
}
auto const& expandedPreset = preset->second.Expanded;
@@ -1292,14 +1350,14 @@ void cmake::SetArgs(const std::vector<std::string>& args)
if (!expandedPreset->ArchitectureStrategy ||
expandedPreset->ArchitectureStrategy ==
- cmCMakePresetsFile::ArchToolsetStrategy::Set) {
+ cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
if (!this->GeneratorPlatformSet) {
this->SetGeneratorPlatform(expandedPreset->Architecture);
}
}
if (!expandedPreset->ToolsetStrategy ||
expandedPreset->ToolsetStrategy ==
- cmCMakePresetsFile::ArchToolsetStrategy::Set) {
+ cmCMakePresetsGraph::ArchToolsetStrategy::Set) {
if (!this->GeneratorToolsetSet) {
this->SetGeneratorToolset(expandedPreset->Toolset);
}
@@ -1325,7 +1383,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
this->DebugTryCompileOn();
}
if (expandedPreset->DebugFind == true) {
- this->SetDebugFindOutputOn(true);
+ this->SetDebugFindOutput(true);
}
}
#endif
@@ -1423,26 +1481,31 @@ void cmake::PrintTraceFormatVersion()
}
}
-void cmake::SetDirectoriesFromFile(const std::string& arg)
+bool cmake::SetDirectoriesFromFile(const std::string& arg)
{
// Check if the argument refers to a CMakeCache.txt or
// CMakeLists.txt file.
std::string listPath;
std::string cachePath;
- bool argIsFile = false;
+ bool is_source_dir = false;
+ bool is_empty_directory = false;
if (cmSystemTools::FileIsDirectory(arg)) {
std::string path = cmSystemTools::CollapseFullPath(arg);
cmSystemTools::ConvertToUnixSlashes(path);
std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
std::string listFile = cmStrCat(path, "/CMakeLists.txt");
+
+ is_empty_directory = true;
if (cmSystemTools::FileExists(cacheFile)) {
cachePath = path;
+ is_empty_directory = false;
}
if (cmSystemTools::FileExists(listFile)) {
listPath = path;
+ is_empty_directory = false;
+ is_source_dir = true;
}
} else if (cmSystemTools::FileExists(arg)) {
- argIsFile = true;
std::string fullPath = cmSystemTools::CollapseFullPath(arg);
std::string name = cmSystemTools::GetFilenameName(fullPath);
name = cmSystemTools::LowerCase(name);
@@ -1458,7 +1521,6 @@ void cmake::SetDirectoriesFromFile(const std::string& arg)
std::string name = cmSystemTools::GetFilenameName(fullPath);
name = cmSystemTools::LowerCase(name);
if (name == "cmakecache.txt"_s || name == "cmakelists.txt"_s) {
- argIsFile = true;
listPath = cmSystemTools::GetFilenamePath(fullPath);
} else {
listPath = fullPath;
@@ -1473,42 +1535,60 @@ void cmake::SetDirectoriesFromFile(const std::string& arg)
if (existingValue) {
this->SetHomeOutputDirectory(cachePath);
this->SetHomeDirectory(*existingValue);
- return;
+ return true;
}
}
}
+ bool no_source_tree = this->GetHomeDirectory().empty();
+ bool no_build_tree = this->GetHomeOutputDirectory().empty();
+
+ // When invoked with a path that points to an existing CMakeCache
+ // This function is called multiple times with the same path
+ const bool passed_same_path = (listPath == this->GetHomeDirectory()) ||
+ (listPath == this->GetHomeOutputDirectory());
+ bool used_provided_path =
+ (passed_same_path || is_source_dir || no_build_tree);
+
// If there is a CMakeLists.txt file, use it as the source tree.
if (!listPath.empty()) {
- this->SetHomeDirectory(listPath);
-
- 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);
- } else {
- // Source directory given on command line. Use current working
- // directory as build tree if -B hasn't been given already
- if (this->GetHomeOutputDirectory().empty()) {
+ // When invoked with a path that points to an existing CMakeCache
+ // This function is called multiple times with the same path
+ if (is_source_dir) {
+ this->SetHomeDirectoryViaCommandLine(listPath, HomeDirArgStyle::Plain);
+ if (no_build_tree) {
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
this->SetHomeOutputDirectory(cwd);
}
+ } else if (no_source_tree && no_build_tree) {
+ this->SetHomeDirectory(listPath);
+
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ } else if (no_build_tree) {
+ this->SetHomeOutputDirectory(listPath);
+ }
+ } else {
+ if (no_source_tree) {
+ // We didn't find a CMakeLists.txt and it wasn't specified
+ // with -S. Assume it is the path to the source tree
+ std::string full = cmSystemTools::CollapseFullPath(arg);
+ this->SetHomeDirectory(full);
+ }
+ if (no_build_tree && !no_source_tree && is_empty_directory) {
+ // passed `-S <path> <build_dir> when build_dir is an empty directory
+ std::string full = cmSystemTools::CollapseFullPath(arg);
+ this->SetHomeOutputDirectory(full);
+ } else if (no_build_tree) {
+ // We didn't find a CMakeCache.txt and it wasn't specified
+ // with -B. Assume the current working directory as the build tree.
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ used_provided_path = false;
}
- return;
}
- if (this->GetHomeDirectory().empty()) {
- // We didn't find a CMakeLists.txt and it wasn't specified
- // with -S. Assume it is the path to the source tree
- std::string full = cmSystemTools::CollapseFullPath(arg);
- this->SetHomeDirectory(full);
- }
- if (this->GetHomeOutputDirectory().empty()) {
- // We didn't find a CMakeCache.txt and it wasn't specified
- // with -B. Assume the current working directory as the build tree.
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->SetHomeOutputDirectory(cwd);
- }
+ return used_provided_path;
}
// at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
@@ -1680,12 +1760,12 @@ bool cmake::CreateAndSetGlobalGenerator(const std::string& name,
}
#ifndef CMAKE_BOOTSTRAP
-void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
+void cmake::PrintPresetList(const cmCMakePresetsGraph& graph) const
{
std::vector<GeneratorInfo> generators;
this->GetRegisteredGenerators(generators, false);
auto filter =
- [&generators](const cmCMakePresetsFile::ConfigurePreset& preset) -> bool {
+ [&generators](const cmCMakePresetsGraph::ConfigurePreset& preset) -> bool {
if (preset.Generator.empty()) {
return true;
}
@@ -1696,16 +1776,46 @@ void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
return it != generators.end();
};
- file.PrintConfigurePresetList(filter);
+ graph.PrintConfigurePresetList(filter);
}
#endif
+void cmake::SetHomeDirectoryViaCommandLine(std::string const& path,
+ HomeDirArgStyle argStyle)
+{
+ bool fromDashS = argStyle == HomeDirArgStyle::Dash_S;
+ static bool homeDirectorySetExplicitly = false;
+ if (path.empty()) {
+ return;
+ }
+
+ auto prev_path = this->GetHomeDirectory();
+ if (prev_path != path && !prev_path.empty()) {
+ const bool ignore_prev_path =
+ (fromDashS || (!fromDashS && !homeDirectorySetExplicitly));
+ const std::string& ignored_path = (ignore_prev_path) ? prev_path : path;
+ this->IssueMessage(MessageType::WARNING,
+ cmStrCat("Ignoring extra path from command line:\n \"",
+ ignored_path, "\""));
+ }
+ if (fromDashS || !homeDirectorySetExplicitly) {
+ this->SetHomeDirectory(path);
+ }
+ homeDirectorySetExplicitly = fromDashS;
+}
+
void cmake::SetHomeDirectory(const std::string& dir)
{
this->State->SetSourceDirectory(dir);
if (this->CurrentSnapshot.IsValid()) {
this->CurrentSnapshot.SetDefinition("CMAKE_SOURCE_DIR", dir);
}
+
+ if (this->State->GetProjectKind() == cmState::ProjectKind::Normal) {
+ this->Messenger->SetTopSource(this->GetHomeDirectory());
+ } else {
+ this->Messenger->SetTopSource(cm::nullopt);
+ }
}
std::string const& cmake::GetHomeDirectory() const
@@ -2155,7 +2265,8 @@ int cmake::ActualConfigure()
"CMakeLists.txt ?");
}
- this->State->SaveVerificationScript(this->GetHomeOutputDirectory());
+ this->State->SaveVerificationScript(this->GetHomeOutputDirectory(),
+ this->Messenger.get());
this->SaveCache(this->GetHomeOutputDirectory());
if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
@@ -2452,7 +2563,7 @@ void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories,
{
this->State->AddGlobCacheEntry(recurse, listDirectories, followSymlinks,
relative, expression, files, variable,
- backtrace);
+ backtrace, this->Messenger.get());
}
std::vector<std::string> cmake::GetAllExtensions() const
@@ -3185,8 +3296,8 @@ std::vector<std::string> cmake::GetDebugConfigs()
int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
std::string config, std::vector<std::string> nativeOptions,
- bool clean, bool verbose, const std::string& presetName,
- bool listPresets)
+ cmBuildOptions& buildOptions, bool verbose,
+ const std::string& presetName, bool listPresets)
{
this->SetHomeDirectory("");
this->SetHomeOutputDirectory("");
@@ -3196,12 +3307,12 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
- cmCMakePresetsFile settingsFile;
+ cmCMakePresetsGraph settingsFile;
auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
- if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) {
cmSystemTools::Error(
cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
- ": ", cmCMakePresetsFile::ResultToString(result)));
+ ": ", cmCMakePresetsGraph::ResultToString(result)));
return 1;
}
@@ -3292,8 +3403,13 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
config = expandedPreset->Configuration;
}
- if (!clean && expandedPreset->CleanFirst) {
- clean = *expandedPreset->CleanFirst;
+ if (!buildOptions.Clean && expandedPreset->CleanFirst) {
+ buildOptions.Clean = *expandedPreset->CleanFirst;
+ }
+
+ if (buildOptions.ResolveMode == PackageResolveMode::Default &&
+ expandedPreset->ResolvePackageReferences) {
+ buildOptions.ResolveMode = *expandedPreset->ResolvePackageReferences;
}
if (!verbose && expandedPreset->Verbose) {
@@ -3432,7 +3548,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs);
return this->GlobalGenerator->Build(
- jobs, "", dir, projName, targets, output, "", config, clean, false,
+ jobs, "", dir, projName, targets, output, "", config, buildOptions,
verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH,
nativeOptions);
}
@@ -3612,6 +3728,26 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b)
cmStateEnums::INTERNAL);
}
+void cmake::SetDebugFindOutputPkgs(std::string const& args)
+{
+ this->DebugFindPkgs.emplace(args);
+}
+
+void cmake::SetDebugFindOutputVars(std::string const& args)
+{
+ this->DebugFindVars.emplace(args);
+}
+
+bool cmake::GetDebugFindOutput(std::string const& var) const
+{
+ return this->DebugFindVars.count(var);
+}
+
+bool cmake::GetDebugFindPkgOutput(std::string const& pkg) const
+{
+ return this->DebugFindPkgs.count(pkg);
+}
+
#if !defined(CMAKE_BOOTSTRAP)
cmMakefileProfilingData& cmake::GetProfilingOutput()
{
diff --git a/Source/cmake.h b/Source/cmake.h
index 3f2b2ed..9c795c5 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -31,7 +31,7 @@
# include <cm3p/json/value.h>
-# include "cmCMakePresetsFile.h"
+# include "cmCMakePresetsGraph.h"
#endif
class cmExternalMakefileProjectGeneratorFactory;
@@ -45,6 +45,7 @@ class cmMakefileProfilingData;
#endif
class cmMessenger;
class cmVariableWatch;
+struct cmBuildOptions;
struct cmDocumentationEntry;
/** \brief Represents a cmake invocation.
@@ -182,6 +183,29 @@ public:
#endif
std::string ReportCapabilities() const;
+ enum class HomeDirArgStyle
+ {
+ Plain,
+ Dash_S,
+ };
+
+ /**
+ * Set the home directory from `-S` or from a known location
+ * that contains a CMakeLists.txt. Will generate warnings
+ * when overriding an existing source directory.
+ *
+ * | args | src dir| warning |
+ * | ----------------- | ------ | -------------- |
+ * | `dirA dirA` | dirA | N/A |
+ * | `-S dirA -S dirA` | dirA | N/A |
+ * | `-S dirA -S dirB` | dirB | Ignoring dirA |
+ * | `-S dirA dirB` | dirA | Ignoring dirB |
+ * | `dirA -S dirB` | dirB | Ignoring dirA |
+ * | `dirA dirB` | dirB | Ignoring dirA |
+ */
+ void SetHomeDirectoryViaCommandLine(std::string const& path,
+ HomeDirArgStyle argStyle);
+
//@{
/**
* Set/Get the home directory (or output directory) in the project. The
@@ -248,7 +272,7 @@ public:
#ifndef CMAKE_BOOTSTRAP
//! Print list of configure presets
- void PrintPresetList(const cmCMakePresetsFile& file) const;
+ void PrintPresetList(const cmCMakePresetsGraph& graph) const;
#endif
//! Return the global generator assigned to this instance of cmake
@@ -486,7 +510,11 @@ public:
//! Do we want debug output from the find commands during the cmake run.
bool GetDebugFindOutput() const { return this->DebugFindOutput; }
- void SetDebugFindOutputOn(bool b) { this->DebugFindOutput = b; }
+ bool GetDebugFindOutput(std::string const& var) const;
+ bool GetDebugFindPkgOutput(std::string const& pkg) const;
+ void SetDebugFindOutput(bool b) { this->DebugFindOutput = b; }
+ void SetDebugFindOutputPkgs(std::string const& args);
+ void SetDebugFindOutputVars(std::string const& args);
//! Do we want trace output during the cmake run.
bool GetTrace() const { return this->Trace; }
@@ -583,8 +611,8 @@ public:
//! run the --build option
int Build(int jobs, std::string dir, std::vector<std::string> targets,
std::string config, std::vector<std::string> nativeOptions,
- bool clean, bool verbose, const std::string& presetName,
- bool listPresets);
+ cmBuildOptions& buildOptions, bool verbose,
+ const std::string& presetName, bool listPresets);
//! run the --open option
bool Open(const std::string& dir, bool dryRun);
@@ -644,7 +672,7 @@ protected:
*/
int CheckBuildSystem();
- void SetDirectoriesFromFile(const std::string& arg);
+ bool SetDirectoriesFromFile(const std::string& arg);
//! Make sure all commands are what they say they are and there is no
/// macros.
@@ -687,7 +715,7 @@ private:
std::string GraphVizFile;
InstalledFilesMap InstalledFiles;
#ifndef CMAKE_BOOTSTRAP
- std::map<std::string, cm::optional<cmCMakePresetsFile::CacheVariable>>
+ std::map<std::string, cm::optional<cmCMakePresetsGraph::CacheVariable>>
UnprocessedPresetVariables;
std::map<std::string, cm::optional<std::string>>
UnprocessedPresetEnvironment;
@@ -704,6 +732,9 @@ private:
std::vector<std::string> TraceOnlyThisSources;
+ std::set<std::string> DebugFindPkgs;
+ std::set<std::string> DebugFindVars;
+
LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
bool LogLevelWasSetViaCLI = false;
bool LogContext = false;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 6090ec4..0554c3e 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <cassert>
+#include <cctype>
#include <climits>
#include <cstdio>
#include <cstring>
@@ -19,6 +20,7 @@
#include <cm3p/uv.h>
+#include "cmBuildOptions.h"
#include "cmCommandLineArgument.h"
#include "cmConsoleBuf.h"
#include "cmDocumentationEntry.h" // IWYU pragma: keep
@@ -90,6 +92,10 @@ const char* cmDocumentationOptions[][2] = {
"useful on one try_compile at a time." },
{ "--debug-output", "Put cmake in a debug mode." },
{ "--debug-find", "Put cmake find in a debug mode." },
+ { "--debug-find-pkg=<pkg-name>[,...]",
+ "Limit cmake debug-find to the comma-separated list of packages" },
+ { "--debug-find-var=<var-name>[,...]",
+ "Limit cmake debug-find to the comma-separated list of result variables" },
{ "--trace", "Put cmake in trace mode." },
{ "--trace-expand", "Put cmake in trace mode with variable expansion." },
{ "--trace-format=<human|json-v1>", "Set the output format of the trace." },
@@ -441,6 +447,7 @@ int do_build(int ac, char const* const* av)
bool cleanFirst = false;
bool foundClean = false;
bool foundNonClean = false;
+ PackageResolveMode resolveMode = PackageResolveMode::Default;
bool verbose = cmSystemTools::HasEnv("VERBOSE");
std::string presetName;
bool listPresets = false;
@@ -474,6 +481,22 @@ int do_build(int ac, char const* const* av)
}
return false;
};
+ auto resolvePackagesLambda = [&](std::string const& value) -> bool {
+ std::string v = value;
+ std::transform(v.begin(), v.end(), v.begin(), ::tolower);
+
+ if (v == "on") {
+ resolveMode = PackageResolveMode::Force;
+ } else if (v == "only") {
+ resolveMode = PackageResolveMode::OnlyResolve;
+ } else if (v == "off") {
+ resolveMode = PackageResolveMode::Disable;
+ } else {
+ return false;
+ }
+
+ return true;
+ };
auto verboseLambda = [&](std::string const&) -> bool {
verbose = true;
return true;
@@ -510,6 +533,8 @@ int do_build(int ac, char const* const* av)
cleanFirst = true;
return true;
} },
+ CommandArgument{ "--resolve-package-references",
+ CommandArgument::Values::One, resolvePackagesLambda },
CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda },
CommandArgument{ "--verbose", CommandArgument::Values::Zero,
verboseLambda },
@@ -635,6 +660,8 @@ int do_build(int ac, char const* const* av)
" --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"
+ " --resolve-package-references={on|only|off}\n"
+ " = Restore/resolve package references during build.\n"
" --verbose, -v = Enable verbose output - if supported - including\n"
" the build commands to be executed. \n"
" -- = Pass remaining options to the native tool.\n"
@@ -652,8 +679,10 @@ int do_build(int ac, char const* const* av)
cmakemainProgressCallback(msg, prog, &cm);
});
+ cmBuildOptions buildOptions(cleanFirst, false, resolveMode);
+
return cm.Build(jobs, std::move(dir), std::move(targets), std::move(config),
- std::move(nativeOptions), cleanFirst, verbose, presetName,
+ std::move(nativeOptions), buildOptions, verbose, presetName,
listPresets);
#endif
}
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 5c27ac1..8921aa0 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -294,7 +294,8 @@ int main()
return exit_code;
// compile rc file with rc.exe
- return process(srcfilename, "", objfile, prefix, binpath + " " + rest);
+ return process(srcfilename, "", objfile, prefix, binpath + " " + rest,
+ std::string(), true);
}
usage("Invalid language specified.");
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index bdddc4e..32c01e5 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -58,7 +58,6 @@
#ifdef _WIN32
# include <fcntl.h> // for _O_BINARY
# include <io.h> // for _setmode
-# include <stdio.h> // for std{out,err} and fileno
#endif
#include <cm/string_view>
@@ -1112,7 +1111,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
int count;
if (countFile) {
if (1 != fscanf(countFile, "%i", &count)) {
- cmSystemTools::Message("Could not read from count file.");
+ std::cerr << "Could not read from count file.\n";
}
fclose(countFile);
} else {
@@ -1426,8 +1425,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
action = cmSystemTools::TarActionExtract;
} break;
default: {
- cmSystemTools::Message(
- std::string("tar: Unknown argument: ") + flag, "Warning");
+ std::cerr << "tar: Unknown argument: " << flag << "\n";
}
}
}
@@ -1448,8 +1446,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
} else if (action == cmSystemTools::TarActionCreate) {
if (files.empty()) {
- cmSystemTools::Message("tar: No files or directories specified",
- "Warning");
+ std::cerr << "tar: No files or directories specified\n";
}
if (!cmSystemTools::CreateTar(outFile, files, compress, verbose, mtime,
format)) {
@@ -1588,7 +1585,11 @@ int cmcmd::HashSumFile(std::vector<std::string> const& args,
std::cerr << "Error: " << filename << " is a directory" << std::endl;
retval++;
} else {
- std::string value = cmSystemTools::ComputeFileHash(filename, algo);
+ std::string value
+#ifndef CMAKE_BOOTSTRAP
+ = cmSystemTools::ComputeFileHash(filename, algo)
+#endif
+ ;
if (value.empty()) {
// To mimic "md5sum/shasum" behavior in a shell:
std::cerr << filename << ": No such file or directory" << std::endl;
@@ -1684,7 +1685,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
return;
}
if (1 != fscanf(progFile, "%i", &count)) {
- cmSystemTools::Message("Could not read from progress file.");
+ std::cerr << "Could not read from progress file.\n";
}
fclose(progFile);
@@ -2135,8 +2136,8 @@ struct NumberFormatter
{
}
};
-std::ostream& operator<<(std::ostream& stream,
- NumberFormatter const& formatter)
+static std::ostream& operator<<(std::ostream& stream,
+ NumberFormatter const& formatter)
{
auto const& flags = stream.flags();
if (formatter.Format == FORMAT_DECIMAL) {
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 7da5971..2253a83 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -192,6 +192,7 @@ endif()
if(KWSYS_USE_Directory)
set(KWSYS_USE_Encoding 1)
set(KWSYS_USE_Status 1)
+ set(KWSYS_USE_SystemTools 1)
endif()
if(KWSYS_USE_DynamicLoader)
set(KWSYS_USE_Encoding 1)
diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake
index 12347b6..6484cc2 100644
--- a/Source/kwsys/CTestConfig.cmake
+++ b/Source/kwsys/CTestConfig.cmake
@@ -3,9 +3,7 @@
set(CTEST_PROJECT_NAME "KWSys")
set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
-if (NOT CTEST_DROP_METHOD STREQUAL "https")
- set(CTEST_DROP_METHOD "http")
-endif ()
+set(CTEST_DROP_METHOD "https")
set(CTEST_DROP_SITE "open.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard")
set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in
index 29a2dd1..8d47340 100644
--- a/Source/kwsys/Configure.hxx.in
+++ b/Source/kwsys/Configure.hxx.in
@@ -16,11 +16,11 @@
@KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP@
#if defined(__SUNPRO_CC) && __SUNPRO_CC > 0x5130 && defined(__has_attribute)
-# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_attribute(x)
+# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) __has_attribute(x)
#elif defined(__has_cpp_attribute)
-# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_cpp_attribute(x)
+# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) __has_cpp_attribute(x)
#else
-# define @KWSYS_NAMESPACE@__has_cpp_attribute(x) 0
+# define @KWSYS_NAMESPACE@_has_cpp_attribute(x) 0
#endif
#if __cplusplus >= 201103L
@@ -31,13 +31,13 @@
#ifndef @KWSYS_NAMESPACE@_FALLTHROUGH
# if __cplusplus >= 201703L && \
- @KWSYS_NAMESPACE@__has_cpp_attribute(fallthrough)
+ @KWSYS_NAMESPACE@_has_cpp_attribute(fallthrough)
# define @KWSYS_NAMESPACE@_FALLTHROUGH [[fallthrough]]
# elif __cplusplus >= 201103L && \
- @KWSYS_NAMESPACE@__has_cpp_attribute(gnu::fallthrough)
+ @KWSYS_NAMESPACE@_has_cpp_attribute(gnu::fallthrough)
# define @KWSYS_NAMESPACE@_FALLTHROUGH [[gnu::fallthrough]]
# elif __cplusplus >= 201103L && \
- @KWSYS_NAMESPACE@__has_cpp_attribute(clang::fallthrough)
+ @KWSYS_NAMESPACE@_has_cpp_attribute(clang::fallthrough)
# define @KWSYS_NAMESPACE@_FALLTHROUGH [[clang::fallthrough]]
# endif
#endif
@@ -45,7 +45,7 @@
# define @KWSYS_NAMESPACE@_FALLTHROUGH static_cast<void>(0)
#endif
-#undef @KWSYS_NAMESPACE@__has_cpp_attribute
+#undef @KWSYS_NAMESPACE@_has_cpp_attribute
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 2e8aa83..d520c14 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -7,6 +7,8 @@
#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(SystemTools.hxx)
+
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -16,15 +18,48 @@
#endif
#include <string>
+#include <utility>
#include <vector>
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include <windows.h>
+
+# include <ctype.h>
+# include <fcntl.h>
+# include <io.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/stat.h>
+# include <sys/types.h>
+#endif
+
namespace KWSYS_NAMESPACE {
class DirectoryInternals
{
public:
+ struct FileData
+ {
+ std::string Name;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ _wfinddata_t FindData;
+#endif
+ FileData(std::string name
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ ,
+ _wfinddata_t data
+#endif
+ )
+ : Name(std::move(name))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ , FindData(std::move(data))
+#endif
+ {
+ }
+ };
// Array of Files
- std::vector<std::string> Files;
+ std::vector<FileData> Files;
// Path to Open'ed directory
std::string Path;
@@ -59,10 +94,45 @@ unsigned long Directory::GetNumberOfFiles() const
const char* Directory::GetFile(unsigned long dindex) const
{
- if (dindex >= this->Internal->Files.size()) {
- return nullptr;
+ return this->Internal->Files[dindex].Name.c_str();
+}
+
+std::string const& Directory::GetFileName(std::size_t i) const
+{
+ return this->Internal->Files[i].Name;
+}
+
+std::string Directory::GetFilePath(std::size_t i) const
+{
+ std::string abs = this->Internal->Path;
+ if (!abs.empty() && abs.back() != '/') {
+ abs += '/';
}
- return this->Internal->Files[dindex].c_str();
+ abs += this->Internal->Files[i].Name;
+ return abs;
+}
+
+bool Directory::FileIsDirectory(std::size_t i) const
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ _wfinddata_t const& data = this->Internal->Files[i].FindData;
+ return (data.attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+#else
+ std::string const& path = this->GetFilePath(i);
+ return kwsys::SystemTools::FileIsDirectory(path);
+#endif
+}
+
+bool Directory::FileIsSymlink(std::size_t i) const
+{
+ std::string const& path = this->GetFilePath(i);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ _wfinddata_t const& data = this->Internal->Files[i].FindData;
+ return kwsys::SystemTools::FileIsSymlinkWithAttr(
+ Encoding::ToWindowsExtendedPath(path), data.attrib);
+#else
+ return kwsys::SystemTools::FileIsSymlink(path);
+#endif
}
const char* Directory::GetPath() const
@@ -81,16 +151,6 @@ void Directory::Clear()
// First Windows platforms
#if defined(_WIN32) && !defined(__CYGWIN__)
-# include <windows.h>
-
-# include <ctype.h>
-# include <fcntl.h>
-# include <io.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-# include <sys/stat.h>
-# include <sys/types.h>
namespace KWSYS_NAMESPACE {
@@ -99,18 +159,21 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
this->Clear();
intptr_t srchHandle;
char* buf;
+ size_t bufLength;
size_t n = name.size();
if (name.back() == '/' || name.back() == '\\') {
- buf = new char[n + 1 + 1];
- sprintf(buf, "%s*", name.c_str());
+ bufLength = n + 1 + 1;
+ buf = new char[bufLength];
+ snprintf(buf, bufLength, "%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];
+ bufLength = n + 2 + 1;
+ buf = new char[bufLength];
if (name.find('\\') != std::string::npos) {
- sprintf(buf, "%s\\*", name.c_str());
+ snprintf(buf, bufLength, "%s\\*", name.c_str());
} else {
- sprintf(buf, "%s/*", name.c_str());
+ snprintf(buf, bufLength, "%s/*", name.c_str());
}
}
struct _wfinddata_t data; // data of current file
@@ -130,7 +193,7 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
// Loop through names
do {
- this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
+ this->Internal->Files.emplace_back(Encoding::ToNarrow(data.name), data);
} while (_wfindnext(srchHandle, &data) != -1);
this->Internal->Path = name;
if (_findclose(srchHandle) == -1) {
@@ -148,13 +211,16 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name,
{
intptr_t srchHandle;
char* buf;
+ size_t bufLength;
size_t n = name.size();
if (name.back() == '/') {
+ bufLength = n + 1 + 1;
buf = new char[n + 1 + 1];
- sprintf(buf, "%s*", name.c_str());
+ snprintf(buf, bufLength, "%s*", name.c_str());
} else {
+ bufLength = n + 2 + 1;
buf = new char[n + 2 + 1];
- sprintf(buf, "%s/*", name.c_str());
+ snprintf(buf, bufLength, "%s/*", name.c_str());
}
struct _wfinddata_t data; // data of current file
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
index d501116..9d0f462 100644
--- a/Source/kwsys/Directory.hxx.in
+++ b/Source/kwsys/Directory.hxx.in
@@ -6,6 +6,7 @@
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/Status.hxx>
+#include <cstddef>
#include <string>
namespace @KWSYS_NAMESPACE@ {
@@ -55,6 +56,26 @@ public:
const char* GetFile(unsigned long) const;
/**
+ * Return the name of the file at the given 0-based index.
+ */
+ std::string const& GetFileName(std::size_t i) const;
+
+ /**
+ * Return the absolute path to the file at the given 0-based index.
+ */
+ std::string GetFilePath(std::size_t i) const;
+
+ /**
+ * Return whether the file at the given 0-based index is a directory.
+ */
+ bool FileIsDirectory(std::size_t i) const;
+
+ /**
+ * Return whether the file at the given 0-based index is a symlink.
+ */
+ bool FileIsSymlink(std::size_t i) const;
+
+ /**
* Return the path to Open'ed directory
*/
const char* GetPath() const;
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index 66ee9ea..8afc2e8 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -275,20 +275,20 @@ const char* DynamicLoader::LastError()
if (length < 1) {
/* FormatMessage failed. Use a default message. */
- _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
- "DynamicLoader encountered error 0x%X. "
- "FormatMessage failed with error 0x%X",
- error, GetLastError());
+ snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%lX. "
+ "FormatMessage failed with error 0x%lX",
+ error, GetLastError());
return str;
}
if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
DYNLOAD_ERROR_BUFFER_SIZE, nullptr, nullptr)) {
/* WideCharToMultiByte failed. Use a default message. */
- _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
- "DynamicLoader encountered error 0x%X. "
- "WideCharToMultiByte failed with error 0x%X",
- error, GetLastError());
+ snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%lX. "
+ "WideCharToMultiByte failed with error 0x%lX",
+ error, GetLastError());
}
return str;
@@ -436,9 +436,14 @@ namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
const std::string& libname, int flags)
{
- CHECK_OPEN_FLAGS(flags, 0, nullptr);
+ CHECK_OPEN_FLAGS(flags, RTLDGlobal, nullptr);
+
+ int llFlags = RTLD_LAZY;
+ if (flags & RTLDGlobal) {
+ llFlags |= RTLD_GLOBAL;
+ }
- return dlopen(libname.c_str(), RTLD_LAZY);
+ return dlopen(libname.c_str(), llFlags);
}
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 539c742..4edd31c 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -73,7 +73,12 @@ public:
// This is currently only supported on Windows.
SearchBesideLibrary = 0x00000001,
- AllOpenFlags = SearchBesideLibrary
+ // Make loaded symbols visible globally
+ //
+ // This is currently only supported on *nix systems.
+ RTLDGlobal = 0x00000002,
+
+ AllOpenFlags = SearchBesideLibrary | RTLDGlobal
};
/** Load a dynamic library into the current process.
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index c6d4b19..fa2c295 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -213,8 +213,8 @@ bool Glob::RecurseDirectory(std::string::size_type start,
fname = kwsys::SystemTools::LowerCase(fname);
#endif
- bool isDir = kwsys::SystemTools::FileIsDirectory(realname);
- bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname);
+ bool isDir = d.FileIsDirectory(cc);
+ bool isSymLink = d.FileIsSymlink(cc);
if (isDir && (!isSymLink || this->RecurseThroughSymlinks)) {
if (isSymLink) {
diff --git a/Source/kwsys/MD5.c b/Source/kwsys/MD5.c
index fb18a5b..76995e2 100644
--- a/Source/kwsys/MD5.c
+++ b/Source/kwsys/MD5.c
@@ -10,6 +10,7 @@
#endif
#include <stddef.h> /* size_t */
+#include <stdint.h> /* uintptr_t */
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memcpy, strlen */
@@ -202,7 +203,7 @@ static void md5_process(md5_state_t* pms, const md5_byte_t* data /*[64]*/)
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
- if (!((data - (const md5_byte_t*)0) & 3)) {
+ if (!((uintptr_t)data & 3)) {
/* data are properly aligned */
X = (const md5_word_t*)data;
} else {
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index a8a15dd..19bf982 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -41,6 +41,12 @@ do.
/* Increase the file descriptor limit for select() before including
related system headers. (Default: 64) */
# define FD_SETSIZE 16384
+#elif defined(__APPLE__)
+/* Increase the file descriptor limit for select() before including
+ related system headers. (Default: 1024) */
+# define _DARWIN_UNLIMITED_SELECT
+# include <limits.h> /* OPEN_MAX */
+# define FD_SETSIZE OPEN_MAX
#endif
#include <assert.h> /* assert */
@@ -2287,7 +2293,8 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
#endif
default:
cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
- sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig);
+ snprintf(cp->ProcessResults[idx].ExitExceptionString,
+ KWSYSPE_PIPE_BUFFER_SIZE + 1, "Signal %d", sig);
break;
}
}
@@ -2540,7 +2547,7 @@ static void kwsysProcessKill(pid_t process_id)
int pid;
if (sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) {
struct stat finfo;
- sprintf(fname, "/proc/%d/stat", pid);
+ snprintf(fname, sizeof(fname), "/proc/%d/stat", pid);
if (stat(fname, &finfo) == 0) {
FILE* f = fopen(fname, "r");
if (f) {
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 8f01684..e97973e 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -29,7 +29,7 @@ a UNIX-style select system call.
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
#include <io.h> /* _unlink */
-#include <stdio.h> /* sprintf */
+#include <stdio.h> /* snprintf */
#include <string.h> /* strlen, strdup */
#ifndef _MAX_FNAME
@@ -1867,18 +1867,18 @@ void kwsysProcessCleanup(kwsysProcess* cp, DWORD error)
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",
- error, GetLastError());
+ snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
+ "Process execution failed with error 0x%lX. "
+ "FormatMessage failed with error 0x%lX",
+ 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());
+ snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
+ "Process execution failed with error 0x%lX. "
+ "WideCharToMultiByte failed with error 0x%lX",
+ error, GetLastError());
}
}
@@ -2144,8 +2144,8 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
case STATUS_NO_MEMORY:
default:
cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
- _snprintf(cp->ProcessResults[idx].ExitExceptionString,
- KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
+ snprintf(cp->ProcessResults[idx].ExitExceptionString,
+ KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
break;
}
}
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index 091334b..d6ae75c 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -457,9 +457,9 @@ static void kwsys_shared_forward_strerror(char* message)
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());
+ snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH,
+ "Error 0x%lX (FormatMessage failed with error 0x%lX)", original,
+ GetLastError());
}
# else
/* Implementation for UNIX. */
diff --git a/Source/kwsys/Status.cxx b/Source/kwsys/Status.cxx
index 503d1e1..edda7a0 100644
--- a/Source/kwsys/Status.cxx
+++ b/Source/kwsys/Status.cxx
@@ -53,7 +53,7 @@ std::string Status::GetString() const
LocalFree(message);
} break;
#endif
- };
+ }
return err;
}
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index f2bf85f..e6cc48f 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1265,9 +1265,10 @@ public:
}
private:
- void* GetRealAddress() const
+ size_t GetRealAddress() const
{
- return (void*)((char*)this->Address - (char*)this->BinaryBaseAddress);
+ return static_cast<size_t>(static_cast<char*>(this->Address) -
+ static_cast<char*>(this->BinaryBaseAddress));
}
std::string GetFileName(const std::string& path) const;
@@ -2789,19 +2790,20 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber()
// ; 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));
+ snprintf(sn, sizeof(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;
@@ -3260,6 +3262,9 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case 0x3b:
this->ChipID.ProcessorName = "Zhaoxin kx6000";
break;
+ case 0x5b:
+ this->ChipID.ProcessorName = "Zhaoxin kh40000";
+ break;
default:
this->ChipID.ProcessorName =
"Unknown IDT\\Centaur\\VIA\\Zhaoxin family";
@@ -3293,6 +3298,9 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case 0x3b:
this->ChipID.ProcessorName = "Zhaoxin kx6000";
break;
+ case 0x5b:
+ this->ChipID.ProcessorName = "Zhaoxin kh40000";
+ break;
default:
this->ChipID.ProcessorName = "Unknown Zhaoxin family";
return false;
@@ -3749,24 +3757,24 @@ long long SystemInformationImplementation::GetProcMemoryAvailable(
ResourceLimitType rlim;
ierr = GetResourceLimit(RLIMIT_DATA, &rlim);
if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
- memAvail = min((long long)rlim.rlim_cur / 1024, memAvail);
+ memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail);
}
ierr = GetResourceLimit(RLIMIT_AS, &rlim);
if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
- memAvail = min((long long)rlim.rlim_cur / 1024, memAvail);
+ memAvail = min(static_cast<long long>(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((long long)rlim.rlim_cur / 1024, memAvail);
+ memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail);
}
ierr = getrlimit(RLIMIT_RSS, &rlim);
if ((ierr == 0) && (rlim.rlim_cur != RLIM_INFINITY)) {
- memAvail = min((long long)rlim.rlim_cur / 1024, memAvail);
+ memAvail = min(static_cast<long long>(rlim.rlim_cur) / 1024, memAvail);
}
#endif
@@ -4068,7 +4076,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
// install ours
struct sigaction sa;
- sa.sa_sigaction = (SigAction)StacktraceSignalHandler;
+ sa.sa_sigaction = static_cast<SigAction>(StacktraceSignalHandler);
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
# ifdef SA_RESTART
sa.sa_flags |= SA_RESTART;
@@ -4564,7 +4572,8 @@ bool SystemInformationImplementation::ParseSysCtl()
this->AvailablePhysicalMemory = 0;
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,
+ if (host_statistics(mach_host_self(), HOST_VM_INFO,
+ reinterpret_cast<host_info_t>(&vmstat),
&count) == KERN_SUCCESS) {
err = kw_sysctlbyname_int64("hw.pagesize", &tempInt64);
if (err == 0) {
@@ -5395,8 +5404,8 @@ bool SystemInformationImplementation::QueryOSInformation()
}
}
- sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion,
- osvi.dwBuildNumber & 0xFFFF);
+ snprintf(operatingSystem, sizeof(operatingSystem), "%ls (Build %ld)",
+ osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
} else
# endif // VER_NT_WORKSTATION
@@ -5439,9 +5448,10 @@ bool SystemInformationImplementation::QueryOSInformation()
// Display version, service pack (if any), and build number.
if (osvi.dwMajorVersion <= 4) {
// NB: NT 4.0 and earlier.
- sprintf(operatingSystem, "version %ld.%ld %ls (Build %ld)",
- osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion,
- osvi.dwBuildNumber & 0xFFFF);
+ snprintf(operatingSystem, sizeof(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) {
// Windows XP and .NET server.
@@ -5467,8 +5477,8 @@ bool SystemInformationImplementation::QueryOSInformation()
}
} else {
// Windows 2000 and everything else.
- sprintf(operatingSystem, "%ls (Build %ld)", osvi.szCSDVersion,
- osvi.dwBuildNumber & 0xFFFF);
+ snprintf(operatingSystem, sizeof(operatingSystem), "%ls (Build %ld)",
+ osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
}
break;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 930d84c..c38b456 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -34,6 +34,10 @@
#include <utility>
#include <vector>
+#ifdef _WIN32
+# include <cwchar>
+#endif
+
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -103,6 +107,9 @@
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
+# ifndef IO_REPARSE_TAG_APPEXECLINK
+# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL)
+# endif
// from ntifs.h, which can only be used by drivers
typedef struct _REPARSE_DATA_BUFFER
{
@@ -132,8 +139,46 @@ typedef struct _REPARSE_DATA_BUFFER
{
UCHAR DataBuffer[1];
} GenericReparseBuffer;
+ struct
+ {
+ ULONG Version;
+ WCHAR StringList[1];
+ // In version 3, there are 4 NUL-terminated strings:
+ // * Package ID
+ // * Entry Point
+ // * Executable Path
+ // * Application Type
+ } AppExecLinkReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+namespace {
+WCHAR* GetAppExecLink(PREPARSE_DATA_BUFFER data, size_t& len)
+{
+ // We only know the layout of version 3.
+ if (data->AppExecLinkReparseBuffer.Version != 3) {
+ return nullptr;
+ }
+
+ WCHAR* pstr = data->AppExecLinkReparseBuffer.StringList;
+
+ // Skip the package id and entry point strings.
+ for (int i = 0; i < 2; ++i) {
+ len = std::wcslen(pstr);
+ if (len == 0) {
+ return nullptr;
+ }
+ pstr += len + 1;
+ }
+
+ // The third string is the executable path.
+ len = std::wcslen(pstr);
+ if (len == 0) {
+ return nullptr;
+ }
+ return pstr;
+}
+}
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
@@ -1343,8 +1388,8 @@ bool SystemTools::FileExists(const std::string& filename)
return false;
}
#if defined(_WIN32)
- DWORD attr =
- GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str());
+ const std::wstring path = Encoding::ToWindowsExtendedPath(filename);
+ DWORD attr = GetFileAttributesW(path.c_str());
if (attr == INVALID_FILE_ATTRIBUTES) {
return false;
}
@@ -1352,12 +1397,38 @@ bool SystemTools::FileExists(const std::string& filename)
if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
// Using 0 instead of GENERIC_READ as it allows reading of file attributes
// even if we do not have permission to read the file itself
- HANDLE handle =
- CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0,
- nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ HANDLE handle = CreateFileW(path.c_str(), 0, 0, nullptr, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (handle == INVALID_HANDLE_VALUE) {
- return false;
+ // A reparse point may be an execution alias (Windows Store app), which
+ // is similar to a symlink but it cannot be opened as a regular file.
+ // We must look at the reparse point data explicitly.
+ handle = CreateFileW(
+ path.c_str(), 0, 0, nullptr, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ DWORD bytesReturned = 0;
+
+ if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned,
+ nullptr)) {
+ CloseHandle(handle);
+ return false;
+ }
+
+ CloseHandle(handle);
+
+ PREPARSE_DATA_BUFFER data =
+ reinterpret_cast<PREPARSE_DATA_BUFFER>(&buffer[0]);
+
+ // Assume that file exists if it is an execution alias.
+ return data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK;
}
CloseHandle(handle);
@@ -2216,7 +2287,7 @@ bool SystemTools::FilesDiffer(const std::string& source,
if (statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0) {
return false;
}
- off_t nleft =
+ auto nleft =
((__int64)statSource.nFileSizeHigh << 32) + statSource.nFileSizeLow;
#else
@@ -3011,18 +3082,13 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
bool SystemTools::FileIsExecutable(const std::string& name)
{
-#if defined(_WIN32)
- return SystemTools::FileExists(name, true);
-#else
return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE);
-#endif
}
-bool SystemTools::FileIsSymlink(const std::string& name)
-{
#if defined(_WIN32)
- std::wstring path = Encoding::ToWindowsExtendedPath(name);
- DWORD attr = GetFileAttributesW(path.c_str());
+bool SystemTools::FileIsSymlinkWithAttr(const std::wstring& path,
+ unsigned long attr)
+{
if (attr != INVALID_FILE_ATTRIBUTES) {
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// FILE_ATTRIBUTE_REPARSE_POINT means:
@@ -3051,9 +3117,17 @@ bool SystemTools::FileIsSymlink(const std::string& name)
(reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
}
return false;
- } else {
- return false;
}
+
+ return false;
+}
+#endif
+
+bool SystemTools::FileIsSymlink(const std::string& name)
+{
+#if defined(_WIN32)
+ std::wstring path = Encoding::ToWindowsExtendedPath(name);
+ return FileIsSymlinkWithAttr(path, GetFileAttributesW(path.c_str()));
#else
struct stat fs;
if (lstat(name.c_str(), &fs) == 0) {
@@ -3164,6 +3238,15 @@ Status SystemTools::ReadSymlink(std::string const& newName,
data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
substituteNameData = data->MountPointReparseBuffer.PathBuffer +
data->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
+ } else if (data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
+ // The reparse buffer is a list of 0-terminated non-empty strings,
+ // terminated by an empty string (0-0). We need the third string.
+ size_t destLen;
+ substituteNameData = GetAppExecLink(data, destLen);
+ if (substituteNameData == nullptr || destLen == 0) {
+ return Status::Windows(ERROR_SYMLINK_NOT_SUPPORTED);
+ }
+ substituteNameLength = static_cast<USHORT>(destLen);
} else {
return Status::Windows(ERROR_REPARSE_TAG_MISMATCH);
}
@@ -3767,6 +3850,32 @@ bool SystemTools::Split(const std::string& str,
return true;
}
+std::string SystemTools::Join(const std::vector<std::string>& list,
+ const std::string& separator)
+{
+ std::string result;
+ if (list.empty()) {
+ return result;
+ }
+
+ size_t total_size = separator.size() * (list.size() - 1);
+ for (const std::string& string : list) {
+ total_size += string.size();
+ }
+
+ result.reserve(total_size);
+ bool needs_separator = false;
+ for (const std::string& string : list) {
+ if (needs_separator) {
+ result += separator;
+ }
+ result += string;
+ needs_separator = true;
+ }
+
+ return result;
+}
+
/**
* Return path of a full filename (no trailing slashes).
* Warning: returned path is converted to Unix slashes format.
@@ -4148,9 +4257,9 @@ std::string SystemTools::MakeCidentifier(const std::string& s)
// Convenience function around std::getline which removes a trailing carriage
// return and can truncate the buffer as needed. Returns true
// if any data were read before the end-of-file was reached.
-bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
- bool* has_newline /* = 0 */,
- long sizeLimit /* = -1 */)
+bool SystemTools::GetLineFromStream(
+ std::istream& is, std::string& line, bool* has_newline /* = 0 */,
+ std::string::size_type sizeLimit /* = std::string::npos */)
{
// Start with an empty line.
line = "";
@@ -4175,7 +4284,7 @@ bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
}
// if we read too much then truncate the buffer
- if (sizeLimit >= 0 && line.size() >= static_cast<size_t>(sizeLimit)) {
+ if (sizeLimit != std::string::npos && line.size() > sizeLimit) {
line.resize(sizeLimit);
}
}
@@ -4526,10 +4635,10 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
}
res += " ";
- sprintf(buffer, "%ld", osvi.dwMajorVersion);
+ snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMajorVersion);
res += buffer;
res += ".";
- sprintf(buffer, "%ld", osvi.dwMinorVersion);
+ snprintf(buffer, sizeof(buffer), "%ld", osvi.dwMinorVersion);
res += buffer;
}
@@ -4549,7 +4658,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
if (lRet == ERROR_SUCCESS) {
res += " Service Pack 6a (Build ";
- sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
+ snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
} else // Windows NT 4.0 prior to SP6a
@@ -4557,7 +4666,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
res += " ";
res += osvi.szCSDVersion;
res += " (Build ";
- sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
+ snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
}
@@ -4568,7 +4677,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
res += " ";
res += osvi.szCSDVersion;
res += " (Build ";
- sprintf(buffer, "%ld", osvi.dwBuildNumber & 0xFFFF);
+ snprintf(buffer, sizeof(buffer), "%ld", osvi.dwBuildNumber & 0xFFFF);
res += buffer;
res += ")";
}
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index e5d115e..acce015 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -214,6 +214,13 @@ public:
char separator);
/**
+ * Joins a vector of strings into a single string, with separator in between
+ * each string.
+ */
+ static std::string Join(const std::vector<std::string>& list,
+ const std::string& separator);
+
+ /**
* Return string with space added between capitalized words
* (i.e. EatMyShorts becomes Eat My Shorts )
* (note that IEatShorts becomes IEat Shorts)
@@ -516,9 +523,9 @@ 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(std::istream& istr, std::string& line,
- bool* has_newline = nullptr,
- long sizeLimit = -1);
+ static bool GetLineFromStream(
+ std::istream& istr, std::string& line, bool* has_newline = nullptr,
+ std::string::size_type sizeLimit = std::string::npos);
/**
* Get the parent directory of the directory or file
@@ -681,6 +688,16 @@ public:
*/
static bool FileIsExecutable(const std::string& name);
+#if defined(_WIN32)
+ /**
+ * Return true if the file with FileAttributes `attr` is a symlink
+ * Only available on Windows. This avoids an expensive `GetFileAttributesW`
+ * call.
+ */
+ static bool FileIsSymlinkWithAttr(const std::wstring& path,
+ unsigned long attr);
+#endif
+
/**
* Return true if the file is a symlink
*/
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index a847462..79bdc98 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -19,7 +19,7 @@ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include <testSystemTools.h>
-int _doLongPathTest()
+static int _doLongPathTest()
{
using namespace kwsys;
static const int LONG_PATH_THRESHOLD = 512;
@@ -77,7 +77,7 @@ int _doLongPathTest()
return res;
}
-int _nonExistentDirectoryTest()
+static int _nonExistentDirectoryTest()
{
using namespace kwsys;
int res = 0;
@@ -105,7 +105,7 @@ int _nonExistentDirectoryTest()
return res;
}
-int _copyDirectoryTest()
+static int _copyDirectoryTest()
{
using namespace kwsys;
const std::string source(TEST_SYSTEMTOOLS_BINARY_DIR
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index 9ba204e..806c01a 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -11,20 +11,20 @@
// Needed for __GLIBC__ test macro.
#ifdef __linux__
# include <features.h>
-#endif
// Will define LIBDL_SO macro on systems with glibc.
-#ifdef __GLIBC__
-# include <gnu/lib-names.h>
+# ifdef __GLIBC__
+# include <gnu/lib-names.h>
// Define to LIBC_SO, if not defined by above header.
-# ifndef LIBDL_SO
-# define LIBDL_SO LIBC_SO
+# ifndef LIBDL_SO
+# define LIBDL_SO LIBC_SO
+# endif
# endif
-#endif
// Define the LIBDL_SO macro, if not defined above.
-#ifndef LIBDL_SO
-# define LIBDL_SO "libdl.so"
+# ifndef LIBDL_SO
+# define LIBDL_SO "libdl.so"
+# endif
#endif
// Work-around CMake dependency scanning limitation. This must
@@ -40,6 +40,10 @@
// left on disk.
#include <testSystemTools.h>
+// For TestDynamicLoaderData, which, though not referenced literally,
+// is referenced semantically.
+#include "testDynload.h"
+
static std::string GetLibName(const char* lname, const char* subdir = nullptr)
{
// Construct proper name of lib
diff --git a/Source/kwsys/testDynload.c b/Source/kwsys/testDynload.c
index 33a431e..83056c0 100644
--- a/Source/kwsys/testDynload.c
+++ b/Source/kwsys/testDynload.c
@@ -6,6 +6,8 @@
# define DL_EXPORT
#endif
+#include "testDynload.h"
+
DL_EXPORT int TestDynamicLoaderData = 0;
DL_EXPORT void TestDynamicLoaderSymbolPointer(void)
diff --git a/Source/kwsys/testDynload.h b/Source/kwsys/testDynload.h
new file mode 100644
index 0000000..dc0d7a1
--- /dev/null
+++ b/Source/kwsys/testDynload.h
@@ -0,0 +1,9 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifdef _WIN32
+# define DL_EXPORT __declspec(dllexport)
+#else
+# define DL_EXPORT
+#endif
+
+extern DL_EXPORT int TestDynamicLoaderData;
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index ee93e8d..1d605cb 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -80,7 +80,7 @@ static int testRobustEncoding()
std::ios::fmtflags const& flags = std::cout.flags();
int ret = 0;
- char cstr[] = { (char)-1, 0 };
+ char cstr[] = { static_cast<char>(-1), 0 };
// this conversion could fail
std::wstring wstr = kwsys::Encoding::ToWide(cstr);
@@ -89,7 +89,7 @@ static int testRobustEncoding()
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::hex << static_cast<int>(wcstr[i]);
}
std::cout << std::endl;
ret++;
@@ -99,7 +99,7 @@ static int testRobustEncoding()
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::hex << static_cast<int>(wcstr[i]);
}
std::cout << std::endl;
ret++;
@@ -160,7 +160,9 @@ static int testCommandLineArguments()
{
int status = 0;
- char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] };
+ char const* argv[2] = {
+ "./app.exe", reinterpret_cast<char const*>(helloWorldStrings[1])
+ };
kwsys::Encoding::CommandLineArguments args(2, argv);
kwsys::Encoding::CommandLineArguments arg2 =
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 6ccc7a7..487da8d 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -295,12 +295,15 @@ static bool CheckFileOperations()
// Reset umask
#ifdef __MSYS__
mode_t fullMask = S_IWRITE;
+ mode_t testPerm = S_IREAD;
#elif defined(_WIN32) && !defined(__CYGWIN__)
// NOTE: Windows doesn't support toggling _S_IREAD.
mode_t fullMask = _S_IWRITE;
+ mode_t testPerm = 0;
#else
// On a normal POSIX platform, we can toggle all permissions.
mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO;
+ mode_t testPerm = S_IRUSR;
#endif
// Test file permissions without umask
@@ -311,7 +314,7 @@ static bool CheckFileOperations()
res = false;
}
- if (!kwsys::SystemTools::SetPermissions(testNewFile, 0)) {
+ if (!kwsys::SystemTools::SetPermissions(testNewFile, testPerm)) {
std::cerr << "Problem with SetPermissions (1) for: " << testNewFile
<< std::endl;
res = false;
@@ -323,17 +326,17 @@ static bool CheckFileOperations()
res = false;
}
- if ((thisPerm & fullMask) != 0) {
+ if ((thisPerm & fullMask) != testPerm) {
std::cerr << "SetPermissions failed to set permissions (1) for: "
<< testNewFile << ": actual = " << thisPerm
- << "; expected = " << 0 << std::endl;
+ << "; expected = " << testPerm << std::endl;
res = false;
}
// While we're at it, check proper TestFileAccess functionality.
bool do_write_test = true;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
- defined(__NetBSD__) || defined(__DragonFly__)
+ defined(__NetBSD__) || defined(__DragonFly__) || defined(__HOS_AIX__)
// If we are running as root on POSIX-ish systems (Linux and the BSDs,
// at least), ignore this check, as root can always write to files.
do_write_test = (getuid() != 0);
@@ -626,6 +629,16 @@ static bool CheckStringOperations()
res = false;
}
+ std::vector<std::string> linesToJoin = { "Mary", "Had", "A", "Little",
+ "Lamb." };
+ std::string joinResult = kwsys::SystemTools::Join(linesToJoin, " ");
+ if (joinResult != "Mary Had A Little Lamb.") {
+ std::cerr << "Problem with Join "
+ "\"Mary Had A Little Lamb.\""
+ << std::endl;
+ res = false;
+ }
+
if (kwsys::SystemTools::ConvertToWindowsOutputPath(
"L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
"\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
@@ -926,7 +939,8 @@ static bool CheckGetLineFromStream()
bool result;
file.seekg(0, std::ios::beg);
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ std::string::npos);
if (!result || line.size() != 5) {
std::cerr << "First line does not have five characters: " << line.size()
<< std::endl;
@@ -934,7 +948,8 @@ static bool CheckGetLineFromStream()
}
file.seekg(0, std::ios::beg);
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ std::string::npos);
if (!result || line.size() != 5) {
std::cerr << "First line does not have five characters after rewind: "
<< line.size() << std::endl;
@@ -943,10 +958,10 @@ static bool CheckGetLineFromStream()
bool ret = true;
- for (size_t size = 1; size <= 5; ++size) {
+ for (std::string::size_type size = 1; size <= 5; ++size) {
file.seekg(0, std::ios::beg);
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
- static_cast<long>(size));
+ result =
+ kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, size);
if (!result || line.size() != size) {
std::cerr << "Should have read " << size << " characters but got "
<< line.size() << std::endl;
@@ -989,7 +1004,8 @@ static bool CheckGetLineFromStreamLongLine()
bool result;
// Read first line.
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ std::string::npos);
if (!result || line != firstLine) {
std::cerr << "First line does not match, expected " << firstLine.size()
<< " characters, got " << line.size() << std::endl;
@@ -1002,7 +1018,8 @@ static bool CheckGetLineFromStreamLongLine()
// Read empty line.
has_newline = false;
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ std::string::npos);
if (!result || !line.empty()) {
std::cerr << "Expected successful read with an empty line, got "
<< line.size() << " characters" << std::endl;
@@ -1015,7 +1032,8 @@ static bool CheckGetLineFromStreamLongLine()
// Read second line.
has_newline = false;
- result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline,
+ std::string::npos);
if (!result || line != secondLine) {
std::cerr << "Second line does not match, expected " << secondLine.size()
<< " characters, got " << line.size() << std::endl;