def __init__(self, log: Log, variableProcessor: VariableProcessor, recipeBuilderSetup: Optional[RecipeBuilderSetup], platformName: str, cmakeConfig: GeneratorCMakeConfig) -> None: super().__init__() self.__Log = log # type: Log self.__VariableProcessor = variableProcessor # type: VariableProcessor self.IsEnabled = recipeBuilderSetup is not None # type: bool self.TargetLocation = None # Optional[ResolvedPath] self.DownloadCacheRootPath = None # Optional[str] self.__TempRootPath = None # Optional[str] self.__TempPipelineRootPath = None # Optional[str] self.InstallRootLocation = None # Optional[ResolvedPath] self.ReadonlyCache_DownloadCacheRootPath = None # Optional[str] if self.IsEnabled and recipeBuilderSetup is not None: targetLocation = recipeBuilderSetup.TargetLocation readonlyCachePath = recipeBuilderSetup.ReadonlyCachePath if not IOUtil.IsAbsolutePath(targetLocation.ResolvedPath): raise Exception( "Install area path is not absolute: '{0}'".format( targetLocation.ResolvedPath)) if not readonlyCachePath is None and not IOUtil.IsAbsolutePath( readonlyCachePath): raise Exception( "Install area readonly cache path is not absolute: '{0}'". format(readonlyCachePath)) self.TargetLocation = targetLocation self.DownloadCacheRootPath = IOUtil.Join( targetLocation.ResolvedPath, ".DownloadCache") self.__TempRootPath = IOUtil.Join(targetLocation.ResolvedPath, ".Temp") baseTempDirectory = IOUtil.Join(self.__TempRootPath, "pipeline") baseTempDirectory = IOUtil.Join(baseTempDirectory, platformName) self.__TempPipelineRootPath = IOUtil.Join( baseTempDirectory, cmakeConfig.GeneratorRecipeShortName) sourceBaseInstallDirectory = IOUtil.Join(targetLocation.SourcePath, platformName) sourceInstallRootPath = IOUtil.Join( sourceBaseInstallDirectory, cmakeConfig.GeneratorRecipeShortName) baseInstallDirectory = IOUtil.Join(targetLocation.ResolvedPath, platformName) installRootPath = IOUtil.Join(baseInstallDirectory, cmakeConfig.GeneratorRecipeShortName) self.InstallRootLocation = ResolvedPath(sourceInstallRootPath, installRootPath) self.ReadonlyCache_DownloadCacheRootPath = None if readonlyCachePath is None else IOUtil.Join( readonlyCachePath, ".DownloadCache")
def __init__(self, log: Log, variableProcessor: VariableProcessor, recipeBuilderSetup: Optional[RecipeBuilderSetup], platformName: str, compilerGeneratorName: str) -> None: super(RecipePathBuilder, self).__init__() self.__Log = log # type: Log self.__VariableProcessor = variableProcessor # type: VariableProcessor self.IsEnabled = recipeBuilderSetup is not None # type: bool self.TargetPath = None # Optional[str] self.DownloadCacheRootPath = None # Optional[str] self.__TempRootPath = None # Optional[str] self.__TempPipelineRootPath = None # Optional[str] self.InstallRootPath = None # Optional[str] self.ReadonlyCache_DownloadCacheRootPath = None # Optional[str] if self.IsEnabled and recipeBuilderSetup is not None: targetPath = recipeBuilderSetup.TargetPath readonlyCachePath = recipeBuilderSetup.ReadonlyCachePath if not IOUtil.IsAbsolutePath(targetPath): raise Exception( "Install area path is not absolute: '{0}'".format( targetPath)) if not readonlyCachePath is None and not IOUtil.IsAbsolutePath( readonlyCachePath): raise Exception( "Install area readonly cache path is not absolute: '{0}'". format(readonlyCachePath)) self.TargetPath = targetPath self.DownloadCacheRootPath = IOUtil.Join(targetPath, ".DownloadCache") self.__TempRootPath = IOUtil.Join(targetPath, ".Temp") baseTempDirectory = IOUtil.Join(self.__TempRootPath, "pipeline") baseTempDirectory = IOUtil.Join(baseTempDirectory, platformName) self.__TempPipelineRootPath = IOUtil.Join(baseTempDirectory, compilerGeneratorName) baseInstallDirectory = IOUtil.Join(targetPath, platformName) self.InstallRootPath = IOUtil.Join(baseInstallDirectory, compilerGeneratorName) self.ReadonlyCache_DownloadCacheRootPath = None if readonlyCachePath is None else IOUtil.Join( readonlyCachePath, ".DownloadCache")
def __GetEnvironmentVariable(self, name: str) -> str: # For cache entries we allow the variable to not be defined, but if it is defned we retrieve is as normal value = IOUtil.TryGetEnvironmentVariable(name) if value is None: raise EnvironmentError( "{0} environment variable not set".format(name)) value = IOUtil.NormalizePath(value) if value is None: raise EnvironmentError( "{0} environment variable not set".format(name)) if not IOUtil.IsAbsolutePath(value): raise EnvironmentError( "{0} environment path '{1}' is not absolute".format( name, value)) if value.endswith("/"): raise EnvironmentError( "{0} environment path '{1}' not allowed to end with '/' or '\'" .format(name, value)) # Create the directory if it didnt exist if not IOUtil.IsDirectory(value) and not IOUtil.Exists(value): self.__Log.LogPrint( "The directory '{0}' did not exist, creating it".format(value)) IOUtil.SafeMakeDirs(value) if not IOUtil.IsDirectory(value): raise EnvironmentError( "The {0} environment variable content '{1}' does not point to a valid directory" .format(name, value)) return value
def __init__(self, filename: str, strPackageName: Optional[str], packageLocation: ToolConfigPackageLocation) -> None: super(PackageFile, self).__init__() if not IOUtil.IsAbsolutePath(filename): raise UsageErrorException() if not isinstance(packageLocation, ToolConfigPackageLocation): raise UsageErrorException() filename = IOUtil.NormalizePath(filename) if not filename.startswith(packageLocation.ResolvedPathEx): raise UsageErrorException( "The filename '{0}' does not belong to the supplied location '{1}'" .format(filename, packageLocation.ResolvedPathEx)) self.Filename = IOUtil.GetFileName(filename) self.RelativeFilePath = filename[ len(packageLocation.ResolvedPathEx ):] # The full relative path to the file self.RelativeDirPath = IOUtil.GetDirectoryName( self.RelativeFilePath) # The relative containing directory self.AbsoluteFilePath = filename # type: str self.AbsoluteDirPath = IOUtil.GetDirectoryName(filename) # type: str self.PackageRootLocation = packageLocation # type: ToolConfigPackageLocation self.PackageName = self.__DeterminePackageNameFromRelativeName( self.RelativeDirPath ) if strPackageName is None else strPackageName # type: str
def __init__(self, log: Log, pythonScriptRoot: str) -> None: super().__init__() if not IOUtil.IsAbsolutePath(pythonScriptRoot): raise Exception("pythonScriptRoot '{0}' is not absolute".format( pythonScriptRoot)) self.Log = log self.PythonScriptRoot = pythonScriptRoot # type: str self.EnvDict = {} # type: Dict[str,str]
def __init__(self, packagePath: str, packageRelativeFilePath: str) -> None: packagePath = IOUtil.NormalizePath(packagePath) packageRelativeFilePath = IOUtil.NormalizePath(packageRelativeFilePath) if not IOUtil.IsAbsolutePath(packagePath): raise Exception("packagePath must be absolute") if IOUtil.IsAbsolutePath(packageRelativeFilePath): raise Exception("packageRelativeFilePath can not be absolute") self.Filename = IOUtil.GetFileName(packageRelativeFilePath) absFilePath = IOUtil.Join(packagePath, packageRelativeFilePath) self.AbsoluteFilePath = absFilePath self.AbsoluteDirPath = IOUtil.GetDirectoryName(absFilePath) self.PackageRelativeFilePath = packageRelativeFilePath self.PackageRelativeDirPath = IOUtil.GetDirectoryName( packageRelativeFilePath)
def __init__(self, userRequestedFNMatchPattern: str) -> None: super().__init__() userRequestedFNMatchPattern = IOUtil.NormalizePath( userRequestedFNMatchPattern) #self.FilterDirPath = IOUtil.NormalizePath(filterDirPath) self.UserRequestedFNMatchPattern = userRequestedFNMatchPattern self.IsAbsolutePattern = IOUtil.IsAbsolutePath( userRequestedFNMatchPattern) self.PatternFileName = IOUtil.GetFileName(userRequestedFNMatchPattern) patternDirectory = IOUtil.GetDirectoryName(userRequestedFNMatchPattern) if not self.IsAbsolutePattern and len( patternDirectory) > 0 and not patternDirectory.startswith('/'): patternDirectory = '/' + patternDirectory self.PatternDirectory = patternDirectory
def __init__(self, filename: str, strPackageName: Optional[str], packageLocation: ToolConfigPackageLocation) -> None: filename = IOUtil.NormalizePath(filename) if not IOUtil.IsAbsolutePath(filename): raise UsageErrorException() rootRelativePath = filename[len(packageLocation.ResolvedPathEx):] super().__init__(IOUtil.GetDirectoryName(rootRelativePath), packageLocation, False) self.Filename = IOUtil.GetFileName(filename) self.RootRelativeFilePath = rootRelativePath # The full root relative path to the file self.AbsoluteFilePath = filename # type: str self.PackageName = self.__DeterminePackageNameFromRelativeName( self.RootRelativeDirPath ) if strPackageName is None else strPackageName # type: str
def __init__(self, log: Log, xmlElement: ET.Element) -> None: super().__init__(log, xmlElement) self.Name = self._ReadAttrib(xmlElement, 'Name') self.Version = self._TryReadAttribAsVersion( xmlElement, 'Version') # type: Optional[Version] self.TargetName = self._TryReadAttrib( xmlElement, 'TargetName') # type: Optional[str] # A optional path that will be specified to cmake self.Path = self._TryReadAttrib(xmlElement, 'Path') # type: Optional[str] self.IfCondition = self._TryReadAttrib( xmlElement, 'If', DependencyCondition.FindPackageAllowed) # type: Optional[str] if self.IfCondition != DependencyCondition.FindPackageAllowed: raise XmlFormatException( "Unsupported IfCondition '{0}' on FindPackage: '{1}'. Expected {2}" .format(self.Version, self.Name, DependencyCondition.FindPackageAllowed)) if self.Path is not None and IOUtil.IsAbsolutePath(self.Path): raise XmlFormatException("Path '{0}' can not be absolute".format( self.Path))
def __init__(self, path: str, packageLocation: ToolConfigPackageLocation, normalize: bool = True) -> None: super().__init__() path = IOUtil.NormalizePath(path) if normalize else path if not isinstance(packageLocation, ToolConfigPackageLocation): raise UsageErrorException() if IOUtil.IsAbsolutePath(path): if not path.startswith(packageLocation.ResolvedPathEx): raise UsageErrorException("The path '{0}' does not belong to the supplied location '{1}'".format(path, packageLocation.ResolvedPathEx)) rootRelativeDirPath = path[len(packageLocation.ResolvedPathEx):] absoluteDirPath = path else: rootRelativeDirPath = path absoluteDirPath = IOUtil.Join(packageLocation.ResolvedPath, path) self.RootRelativeDirPath = rootRelativeDirPath # The root relative containing directory self.AbsoluteDirPath = absoluteDirPath # type: str self.PackageRootLocation = packageLocation # type: ToolConfigPackageLocation
def Process(self, currentDirPath: str, toolConfig: ToolConfig, localToolConfig: LocalToolConfig) -> None: config = Config(self.Log, toolConfig, localToolConfig.PackageConfigurationType, localToolConfig.BuildVariantsDict, localToolConfig.AllowDevelopmentPlugins) # create a config we control and that can be used to just build the tool recipe's configToolCheck = Config(self.Log, toolConfig, PluginSharedValues.TYPE_DEFAULT, localToolConfig.BuildVariantsDict, localToolConfig.AllowDevelopmentPlugins) if localToolConfig.DryRun: config.ForceDisableAllWrite() configToolCheck.ForceDisableAllWrite() self.__CheckUserArgs(localToolConfig.ClangFormatArgs, "formatArgs") self.__CheckUserArgs(localToolConfig.ClangTidyArgs, "tidyArgs") self.__CheckUserArgs(localToolConfig.ClangTidyPostfixArgs, "tidyPostfixArgs") applyClangFormat = toolConfig.ClangFormatConfiguration is not None and localToolConfig.ClangFormat applyClangTidy = toolConfig.ClangTidyConfiguration is not None and localToolConfig.ClangTidy if localToolConfig.IgnoreNotSupported or ( (localToolConfig.ScanSource or applyClangFormat) and not applyClangTidy): config.IgnoreNotSupported = True configToolCheck.IgnoreNotSupported = True packageFilters = localToolConfig.BuildPackageFilters # Get the platform and see if its supported platform = PluginConfig.GetGeneratorPluginById( localToolConfig.PlatformName, False) PlatformUtil.CheckBuildPlatform(platform.Name) generatorContext = GeneratorContext(config, config.ToolConfig.Experimental, platform) config.LogPrint("Active platform: {0}".format(platform.Name)) packageRecipeResultManager = None # type: Optional[PackageRecipeResultManager] toolPackageNames = [] if applyClangFormat or applyClangTidy: if applyClangFormat: if toolConfig.ClangFormatConfiguration is None: raise Exception("internal error") toolPackageNames.append( toolConfig.ClangFormatConfiguration.RecipePackageName) if applyClangTidy: if toolConfig.ClangTidyConfiguration is None: raise Exception("internal error") toolPackageNames.append( toolConfig.ClangTidyConfiguration.RecipePackageName) packageRecipeResultManager = ForceCheckBuildTools( configToolCheck, generatorContext, toolPackageNames) searchDir = currentDirPath if localToolConfig.File is not None and IOUtil.IsAbsolutePath( localToolConfig.File): searchDir = IOUtil.GetDirectoryName(localToolConfig.File) closestGenFilePath = FileFinder.TryFindClosestFileInRoot( config, toolConfig, searchDir, config.GenFileName) if closestGenFilePath is None: closestGenFilePath = searchDir if (self.Log.Verbosity >= 4): self.Log.LogPrint("Closest '{0}' file path: '{1}'".format( toolConfig.GenFileName, closestGenFilePath)) packageProcess = None # type: Optional[MainFlow.PackageLoadAndResolveProcess] packages = None discoverFeatureList = '*' in packageFilters.FeatureNameList if discoverFeatureList or localToolConfig.Project is None or localToolConfig.ScanSource or applyClangFormat or applyClangTidy: if discoverFeatureList: config.LogPrint( "No features specified, so using package to determine them" ) if localToolConfig.ScanSource or applyClangFormat or applyClangTidy or discoverFeatureList: packageProcess = self.__CreatePackageProcess( config, toolConfig.GetMinimalConfig(), closestGenFilePath, localToolConfig.Recursive, generatorContext.Platform, toolPackageNames) packageProcess.Resolve(generatorContext, packageFilters, applyClangTidy, False) packages = packageProcess.Packages topLevelPackage = PackageListUtil.GetTopLevelPackage(packages) if discoverFeatureList: packageFilters.FeatureNameList = [ entry.Name for entry in topLevelPackage.ResolvedAllUsedFeatures ] customPackageFileFilter = None # type: Optional[CustomPackageFileFilter] if not localToolConfig.ScanSource and not applyClangFormat and not applyClangTidy: Validate.ValidatePlatform(config, localToolConfig.PlatformName, packageFilters.FeatureNameList) if packageProcess is None: packageProcess = self.__CreatePackageProcess( config, toolConfig.GetMinimalConfig(), closestGenFilePath, localToolConfig.Recursive, generatorContext.Platform, toolPackageNames) if not packageProcess.IsFullResolve or packages is None: # For now this requires a full resolve (but basically it only requires basic + files) packages = packageProcess.Resolve(generatorContext, packageFilters, applyClangTidy, True) topLevelPackage = PackageListUtil.GetTopLevelPackage(packages) RecipeBuilder.ValidateInstallationForPackages( config, generatorContext, topLevelPackage.ResolvedBuildOrder) else: if localToolConfig.File is not None: # Delay extension validation customPackageFileFilter = CustomPackageFileFilter( localToolConfig.File) theTopLevelPackage = None # type: Optional[Package] filteredPackageList = [] # type: List[Package] if applyClangTidy or applyClangFormat or localToolConfig.ScanSource: addExternals = applyClangTidy filteredPackageList, theTopLevelPackage = self.__PreparePackages( self.Log, localToolConfig, packageProcess, generatorContext, packageFilters, addExternals, packages, config.IsSDKBuild, applyClangTidy, config) if len(filteredPackageList) <= 0: self.Log.DoPrint("No supported packages left to process") return if applyClangTidy: self.__ApplyClangTidy(self.Log, toolConfig, localToolConfig, packageRecipeResultManager, theTopLevelPackage, filteredPackageList, platform, config, generatorContext, customPackageFileFilter) if applyClangFormat: self.__ApplyClangFormat(self.Log, toolConfig, localToolConfig, packageRecipeResultManager, filteredPackageList, customPackageFileFilter) # Scan source after 'format' to ensure we dont warn about stuff that has been fixed if localToolConfig.ScanSource: self.__ApplyScanSource(self.Log, localToolConfig, config.IsSDKBuild, config.DisableWrite, filteredPackageList, customPackageFileFilter)
def Capture(log: Log, runCommand: List[str], pythonScriptRoot: str, envNameList: List[str]) -> Dict[str, str]: """ param: runCommand: the command we should run. param: pythonScriptRoot: The root location of the FslBuild.py tools (this must be a absolute path) This will be joined with the FslBuildDump.py name to get the absolute path to the python script. """ if not IOUtil.IsAbsolutePath(pythonScriptRoot): raise Exception("pythonScriptRoot '{0}' is not absolute".format(pythonScriptRoot)) # Validate that the input is in the correct format and create a initial dict entryDict = {} # type: Dict[str,str] for envEntry in envNameList: if not (envEntry.startswith("$(") and envEntry.endswith(")")): raise Exception("Environment variable not in the correct $(NAME) format {0}".format(envEntry)) strippedEntry = envEntry[2:-1] entryDict[envEntry] = strippedEntry log.LogPrintVerbose(4, "Trying to capture environment variables: {0}".format(envNameList)) # call a custom python script with the stripped argument list using the 'generator' run script # the scripts main role is to dump the listed environment variables to screen in a 'json dictionary' format that can be easily captured and # decoded. # Call generator run script (captured) # 'use the "FslBuildDumpEnv --Env [ENV1,ENV2]" script to generate a json dump for the env variables strEnv = "[{0}]".format(",".join(entryDict.values())) commandName = 'FslBuildDumpEnv.py' absCommandName = IOUtil.Join(pythonScriptRoot, commandName) cmdList = [absCommandName, '--AllowNotFound', '--Enclose', '--Env', strEnv] runCommand += cmdList content = LocalUtil.TryRun(log, runCommand) if content is None: raise Exception("Failed to capture virtual variant environment variables {0}".format(envNameList)) # Parse captured json output strJson = LocalUtil.ExtractJson(content) # Decode json jsonDict = json.loads(strJson) finalDict = {} # type: Dict[str,str] for key, value in jsonDict.items(): if not isinstance(key, str) or not isinstance(value, str): LocalUtil.DumpCapture(log, 4, content) raise Exception("captured json decode failed") if not key in jsonDict: LocalUtil.DumpCapture(log, 4, content) raise Exception("Capture contained wrong key: '{0}".format(key)) finalDict[key] = value # Ensure that all the requested entries are present if len(finalDict) != len(entryDict): missingKeys = [] for key in entryDict: if not key in finalDict: missingKeys.append(key) LocalUtil.DumpCapture(log, 4, content) raise Exception("The Captured environment variable output is missing for: {0}".format(missingKeys)) log.LogPrintVerbose(4, "Captured environment variables: {0}".format(finalDict)) return finalDict
def Process(self, currentDirPath: str, toolConfig: ToolConfig, localToolConfig: LocalToolConfig) -> None: #self.Log.LogPrintVerbose(2, "*** Forcing the legacy clang tidy mode ***") #localToolConfig.Legacy = True config = Config(self.Log, toolConfig, localToolConfig.PackageConfigurationType, localToolConfig.BuildVariantsDict, localToolConfig.AllowDevelopmentPlugins) # create a config we control and that can be used to just build the tool recipe's configToolCheck = Config(self.Log, toolConfig, PluginSharedValues.TYPE_DEFAULT, localToolConfig.BuildVariantsDict, localToolConfig.AllowDevelopmentPlugins) if localToolConfig.DryRun: config.ForceDisableAllWrite() configToolCheck.ForceDisableAllWrite() self.__CheckUserArgs(localToolConfig.ClangFormatArgs, "formatArgs") self.__CheckUserArgs(localToolConfig.ClangTidyArgs, "tidyArgs") self.__CheckUserArgs(localToolConfig.ClangTidyPostfixArgs, "tidyPostfixArgs") applyClangFormat = toolConfig.ClangFormatConfiguration is not None and localToolConfig.ClangFormat applyClangTidy = toolConfig.ClangTidyConfiguration is not None and localToolConfig.ClangTidy if localToolConfig.IgnoreNotSupported or ( (localToolConfig.ScanSource or applyClangFormat) and not applyClangTidy): config.IgnoreNotSupported = True configToolCheck.IgnoreNotSupported = True packageFilters = localToolConfig.BuildPackageFilters # Get the platform and see if its supported buildVariantConfig = BuildVariantConfigUtil.GetBuildVariantConfig( localToolConfig.BuildVariantsDict) if localToolConfig.Legacy and applyClangTidy and config.ToolConfig.CMakeConfiguration is not None: # For the LEGACY clangTidy implementation we disable allow find package for the build checks for now as we dont use cmake for those # We basically have to update the tidy pass to utilize ninja+cmake for the tidy pass so that find_package will work self.Log.LogPrintVerbose(2, "Force disabling 'AllowFindPackage'") config.ToolConfig.CMakeConfiguration.SetAllowFindPackage(False) cmakeUserConfig = localToolConfig.GetUserCMakeConfig() if not localToolConfig.Legacy and applyClangTidy: config.LogPrintVerbose( 2, "Forcing the ninja generator for clang tidy") cmakeUserConfig.GeneratorName = "Ninja" generator = self.ToolAppContext.PluginConfigContext.GetGeneratorPluginById( localToolConfig.PlatformName, localToolConfig.Generator, buildVariantConfig, config.ToolConfig.DefaultPackageLanguage, config.ToolConfig.CMakeConfiguration, cmakeUserConfig, True) PlatformUtil.CheckBuildPlatform(generator.PlatformName) generatorContext = GeneratorContext(config, self.ErrorHelpManager, packageFilters.RecipeFilterManager, config.ToolConfig.Experimental, generator) self.Log.LogPrint("Active platform: {0}".format( generator.PlatformName)) packageRecipeResultManager = None # type: Optional[PackageRecipeResultManager] toolPackageNamesSet = set() toolPackageNames = [] if applyClangFormat or applyClangTidy: if applyClangFormat: if toolConfig.ClangFormatConfiguration is None: raise Exception("internal error") toolPackageNamesSet.add( toolConfig.ClangFormatConfiguration.RecipePackageName) toolPackageNamesSet.add( toolConfig.ClangFormatConfiguration.NinjaRecipePackageName) if applyClangTidy: if toolConfig.ClangTidyConfiguration is None: raise Exception("internal error") toolPackageNamesSet.add( toolConfig.ClangTidyConfiguration.ClangRecipePackageName) toolPackageNamesSet.add(toolConfig.ClangTidyConfiguration. ClangTidyRecipePackageName) toolPackageNamesSet.add( toolConfig.ClangTidyConfiguration.NinjaRecipePackageName) toolPackageNames = list(toolPackageNamesSet) packageRecipeResultManager = ForceCheckBuildTools( configToolCheck, generatorContext, toolPackageNames) searchDir = currentDirPath if localToolConfig.File is not None: localToolConfig.File = IOUtil.NormalizePath(localToolConfig.File) if IOUtil.IsAbsolutePath(localToolConfig.File): searchDir = IOUtil.GetDirectoryName(localToolConfig.File) closestGenFilePath = FileFinder.TryFindClosestFileInRoot( config, toolConfig, searchDir, config.GenFileName) if closestGenFilePath is None: closestGenFilePath = searchDir if self.Log.Verbosity >= 4: self.Log.LogPrint("Closest '{0}' file path: '{1}'".format( toolConfig.GenFileName, closestGenFilePath)) packageProcess = None # type: Optional[MainFlow.PackageLoadAndResolveProcess] packages = None discoverFeatureList = '*' in packageFilters.FeatureNameList if discoverFeatureList or localToolConfig.Project is None or localToolConfig.ScanSource or applyClangFormat or applyClangTidy: if discoverFeatureList: config.LogPrint( "No features specified, so using package to determine them" ) if localToolConfig.ScanSource or applyClangFormat or applyClangTidy or discoverFeatureList: packageProcess = self.__CreatePackageProcess( config, toolConfig.GetMinimalConfig(generator.CMakeConfig), closestGenFilePath, localToolConfig.Recursive, generatorContext.Platform, toolPackageNames) packageProcess.Resolve(generatorContext, packageFilters, applyClangTidy, False) packages = packageProcess.Packages topLevelPackage = PackageListUtil.GetTopLevelPackage(packages) if discoverFeatureList: packageFilters.FeatureNameList = [ entry.Name for entry in topLevelPackage.ResolvedAllUsedFeatures ] customPackageFileFilter = None # type: Optional[CustomPackageFileFilter] if not localToolConfig.ScanSource and not applyClangFormat and not applyClangTidy: Validate.ValidatePlatform(config, localToolConfig.PlatformName, packageFilters.FeatureNameList) if packageProcess is None: packageProcess = self.__CreatePackageProcess( config, toolConfig.GetMinimalConfig(generator.CMakeConfig), closestGenFilePath, localToolConfig.Recursive, generatorContext.Platform, toolPackageNames) if not packageProcess.IsFullResolve or packages is None: # For now this requires a full resolve (but basically it only requires basic + files) packages = packageProcess.Resolve(generatorContext, packageFilters, applyClangTidy, True) topLevelPackage = PackageListUtil.GetTopLevelPackage(packages) RecipeBuilder.ValidateInstallationForPackages( config, config.SDKPath, generatorContext, topLevelPackage.ResolvedBuildOrder) else: if localToolConfig.File is not None: # Delay extension validation customPackageFileFilter = CustomPackageFileFilter( localToolConfig.File) theTopLevelPackage = None # type: Optional[Package] filteredPackageList = [] # type: List[Package] if applyClangTidy or applyClangFormat or localToolConfig.ScanSource: addExternals = applyClangTidy filteredPackageList, theTopLevelPackage = self.__PreparePackages( self.Log, localToolConfig, packageProcess, generatorContext, packageFilters, addExternals, packages, config.IsSDKBuild, applyClangTidy, config) if len(filteredPackageList) <= 0: self.Log.DoPrint("No supported packages left to process") return if applyClangTidy: self.__ApplyClangTidy(self.Log, toolConfig, localToolConfig, packageRecipeResultManager, theTopLevelPackage, filteredPackageList, generator, config, generatorContext, customPackageFileFilter) if applyClangFormat: self.__ApplyClangFormat(self.Log, toolConfig, localToolConfig, packageRecipeResultManager, filteredPackageList, customPackageFileFilter, generatorContext.CMakeConfig) # Scan source after 'format' to ensure we dont warn about stuff that has been fixed if localToolConfig.ScanSource: self.__ApplyScanSource(self.Log, localToolConfig, config.IsSDKBuild, config.DisableWrite, filteredPackageList, customPackageFileFilter)