protected override void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result) { var asset = (EffectLogAsset)assetItem.Asset; var originalSourcePath = assetItem.FullPath; result.ShouldWaitForPreviousBuilds = true; result.BuildSteps = new AssetBuildStep(assetItem) { new EffectLogBuildStep(context, originalSourcePath, assetItem) }; }
/// <summary> /// Compile the current package session. /// That is generate the list of build steps to execute to create the package assets. /// </summary> public AssetCompilerResult Compile(AssetCompilerContext compilerContext) { if (compilerContext == null) throw new ArgumentNullException("compilerContext"); var result = new AssetCompilerResult(); var assets = packageCompilerSource.GetAssets(result).ToList(); if (result.HasErrors) { return result; } var defaultAssetsCompiler = new DefaultAssetsCompiler(assets); defaultAssetsCompiler.AssetCompiled += OnAssetCompiled; // Add default compilers compilers.Clear(); compilers.Add(defaultAssetsCompiler); // Compile using all PackageCompiler foreach (var compiler in compilers) { var compilerResult = compiler.Compile(compilerContext); compilerResult.CopyTo(result); while (compilerResult.BuildSteps.Count > 0) { var step = compilerResult.BuildSteps[0]; compilerResult.BuildSteps.RemoveAt(0); result.BuildSteps.Add(step); } } return result; }
public EffectCompileCommand(AssetCompilerContext context, UDirectory baseUrl, string effectName, CompilerParameters compilerParameters) { this.context = context; this.baseUrl = baseUrl; this.effectName = effectName; this.compilerParameters = compilerParameters; }
protected override void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result) { var asset = (SkeletonAsset)assetItem.Asset; var assetSource = GetAbsolutePath(assetItem, asset.Source); var extension = assetSource.GetFileExtension(); var buildStep = new AssetBuildStep(assetItem); var importModelCommand = ImportModelCommand.Create(extension); if (importModelCommand == null) { result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", extension, assetSource); return; } importModelCommand.SourcePath = assetSource; importModelCommand.Location = targetUrlInStorage; importModelCommand.Mode = ImportModelCommand.ExportMode.Skeleton; importModelCommand.ScaleImport = asset.ScaleImport; importModelCommand.PivotPosition = asset.PivotPosition; importModelCommand.SkeletonNodesWithPreserveInfo = asset.NodesWithPreserveInfo; buildStep.Add(importModelCommand); result.BuildSteps = buildStep; }
protected override void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result) { var url = EffectCompilerBase.DefaultSourceShaderFolder + "/" + Path.GetFileName(assetItem.FullPath); var asset = (EffectShaderAsset)assetItem.Asset; var originalSourcePath = assetItem.FullPath; result.BuildSteps = new AssetBuildStep(assetItem) { new ImportStreamCommand { SourcePath = originalSourcePath, Location = url, SaveSourcePath = true } }; var shaderLocations = (ConcurrentDictionary<string, string>)context.Properties.GetOrAdd(ShaderLocationsKey, key => new ConcurrentDictionary<string, string>()); // Store directly this into the context TODO this this temporary shaderLocations[url] = originalSourcePath; }
/// <summary> /// Compiles the package contained in the given context and add the resulting build steps in the <see cref="AssetCompilerResult"/> /// </summary> /// <param name="context">The context which contains the package to compile.</param> /// <param name="result">The <see cref="AssetCompilerResult"/> where the build steps will be added.</param> /// <returns></returns> protected static BuildStep CompilePackage(AssetCompilerContext context, AssetCompilerResult result) { // compile the fake package (create the build steps) var assetPackageCompiler = new PackageCompiler(); var dependenciesCompileResult = assetPackageCompiler.Compile(context); // Create the result build steps if not existing yet if (result.BuildSteps == null) result.BuildSteps = new ListBuildStep(); // Add the dependencies build steps to the current result result.BuildSteps.Add(dependenciesCompileResult.BuildSteps); // Copy log the dependencies result to the current result dependenciesCompileResult.CopyTo(result); return dependenciesCompileResult.BuildSteps; }
protected override void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result) { var asset = (ModelAsset)assetItem.Asset; // Get absolute path of asset source on disk var assetDirectory = assetItem.FullPath.GetParent(); var assetSource = UPath.Combine(assetDirectory, asset.Source); var gameSettingsAsset = context.GetGameSettingsAsset(); var renderingSettings = gameSettingsAsset.Get<RenderingSettings>(); var allow32BitIndex = renderingSettings.DefaultGraphicsProfile >= GraphicsProfile.Level_9_2; var allowUnsignedBlendIndices = context.GetGraphicsPlatform(assetItem.Package) != GraphicsPlatform.OpenGLES; var extension = asset.Source.GetFileExtension(); // Find skeleton asset, if any AssetItem skeleton = null; if (asset.Skeleton != null) skeleton = assetItem.Package.FindAssetFromAttachedReference(asset.Skeleton); var importModelCommand = ImportModelCommand.Create(extension); if (importModelCommand == null) { result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", extension, assetSource); return; } importModelCommand.Mode = ImportModelCommand.ExportMode.Model; importModelCommand.SourcePath = assetSource; importModelCommand.Location = targetUrlInStorage; importModelCommand.Allow32BitIndex = allow32BitIndex; importModelCommand.AllowUnsignedBlendIndices = allowUnsignedBlendIndices; importModelCommand.Materials = asset.Materials; importModelCommand.ScaleImport = asset.ScaleImport; importModelCommand.PivotPosition = asset.PivotPosition; importModelCommand.SkeletonUrl = skeleton?.Location; result.BuildSteps = new AssetBuildStep(assetItem) { importModelCommand }; }
/// <summary> /// Compile the current package session. /// That is generate the list of build steps to execute to create the package assets. /// </summary> public AssetCompilerResult Compile(AssetCompilerContext compilerContext) { if (compilerContext == null) throw new ArgumentNullException("compilerContext"); if (compilerContext.Package == null) { throw new ArgumentException("Expecting a non null package", "compilerContext"); } if (compilerContext.Package.Session == null) { throw new ArgumentException("Expecting a package attached to a session", "compilerContext"); } var result = new AssetCompilerResult(); // Check integrity of the packages var packageAnalysis = new PackageSessionAnalysis(compilerContext.Package.Session, new PackageAnalysisParameters()); packageAnalysis.Run(result); if (result.HasErrors) { return result; } // Add default compilers compilers.Clear(); var defaultAssetsCompiler = new DefaultAssetsCompiler(); defaultAssetsCompiler.AssetCompiled += OnAssetCompiled; compilers.Add(defaultAssetsCompiler); var packagesProcessed = new HashSet<Package>(); RecursiveCompile(result, compilerContext, packagesProcessed); return result; }
private static EffectCompilerBase GetOrCreateEffectCompiler(AssetCompilerContext context) { lock (context) { var compiler = context.Properties.Get(CompilerKey); if (compiler == null) { // Create compiler var effectCompiler = new Shaders.Compiler.EffectCompiler(); effectCompiler.SourceDirectories.Add(EffectCompilerBase.DefaultSourceShaderFolder); compiler = new EffectCompilerCache(effectCompiler); context.Properties.Set(CompilerKey, compiler); var shaderLocations = context.Properties.Get(EffectShaderAssetCompiler.ShaderLocationsKey); // Temp copy URL to absolute file path to inform the compiler the absolute file location // of all pdxsl files. if (shaderLocations != null) { foreach (var shaderLocation in shaderLocations) { effectCompiler.UrlToFilePath[shaderLocation.Key] = shaderLocation.Value; } } } return compiler; } }
private BuildResultCode BuildMaster() { assetLogger = new RemoteLogForwarder(builderOptions.Logger, builderOptions.LogPipeNames); GlobalLogger.GlobalMessageLogged += assetLogger; // TODO handle solution file + package-id ? // When the current platform is not on windows, we need to make sure that all plugins are build, so we // setup auto-compile when loading the session var sessionLoadParameters = new PackageLoadParameters { AutoCompileProjects = builderOptions.Platform != PlatformType.Windows || builderOptions.ProjectConfiguration != "Debug", // Avoid compiling if Windows|Debug ExtraCompileProperties = builderOptions.ExtraCompileProperties, }; // Loads the root Package var projectSessionResult = PackageSession.Load(builderOptions.PackageFile, sessionLoadParameters); if (projectSessionResult.HasErrors) { projectSessionResult.CopyTo(builderOptions.Logger); return BuildResultCode.BuildError; } var projectSession = projectSessionResult.Session; // Check build configuration var package = projectSession.LocalPackages.First(); // Check build profile var sharedProfile = package.Profiles.FindSharedProfile(); var buildProfile = package.Profiles.FirstOrDefault(pair => pair.Name == builderOptions.BuildProfile); if (buildProfile == null) { builderOptions.Logger.Error("Unable to find profile [{0}] in package [{1}]", builderOptions.BuildProfile, package.FullPath); return BuildResultCode.BuildError; } // Setup variables var buildDirectory = builderOptions.BuildDirectory; var outputDirectory = builderOptions.OutputDirectory; // Builds the project var assetBuilder = new PackageCompiler(); assetBuilder.AssetCompiled += RegisterBuildStepProcessedHandler; // Create context var context = new AssetCompilerContext { Package = package, Platform = builderOptions.Platform }; // Copy properties from shared profiles to context properties if (sharedProfile != null) { foreach (var propertyValue in sharedProfile.Properties) context.Properties.Set(propertyValue.Key, propertyValue.Value); } context.Properties.Set(Paradox.Assets.ParadoxConfig.GraphicsPlatform, builderOptions.GraphicsPlatform.HasValue ? builderOptions.GraphicsPlatform.Value : builderOptions.GetDefaultGraphicsPlatform()); // Copy properties from build profile foreach (var propertyValue in buildProfile.Properties) { context.Properties.Set(propertyValue.Key, propertyValue.Value); } var assetBuildResult = assetBuilder.Compile(context); assetBuildResult.CopyTo(builderOptions.Logger); if (assetBuildResult.HasErrors) return BuildResultCode.BuildError; // Create the builder var indexName = "index." + builderOptions.BuildProfile; builder = new Builder(buildDirectory, builderOptions.BuildProfile, indexName, "InputHashes", builderOptions.Logger) { ThreadCount = builderOptions.ThreadCount }; builder.MonitorPipeNames.AddRange(builderOptions.MonitorPipeNames); // Add build steps generated by AssetBuilder builder.Root.Add(assetBuildResult.BuildSteps); // Run builder var result = builder.Run(Builder.Mode.Build); builder.WriteIndexFile(false); // Fill list of bundles var bundlePacker = new BundlePacker(); bundlePacker.Build(builderOptions.Logger, projectSession, buildProfile, indexName, outputDirectory, builder.DisableCompressionIds); // Flush and close logger GlobalLogger.GlobalMessageLogged -= assetLogger; assetLogger.Dispose(); return result; }
/// <summary> /// Compile the required build step necessary to produce the desired output item. /// </summary> /// <param name="context">The context.</param> /// <param name="compilationResult">The compilation result.</param> /// <param name="assetItem">The asset item.</param> public ListBuildStep CompileItem(AssetCompilerContext context, AssetCompilerResult compilationResult, AssetItem assetItem) { // First try to find an asset compiler for this particular asset. IAssetCompiler compiler; try { compiler = compilerRegistry.GetCompiler(assetItem.Asset.GetType(), compilationContext); } catch (Exception ex) { compilationResult.Error($"Cannot find a compiler for asset [{assetItem.Id}] from path [{assetItem.Location}]", ex); return(null); } if (compiler == null) { return(null); } // Second we are compiling the asset (generating a build step) try { var resultPerAssetType = compiler.Prepare(context, assetItem); // Raise the AssetCompiled event. AssetCompiled?.Invoke(this, new AssetCompiledArgs(assetItem, resultPerAssetType)); // TODO: See if this can be unified with PackageBuilder.BuildStepProcessed var assetFullPath = assetItem.FullPath.ToWindowsPath(); foreach (var message in resultPerAssetType.Messages) { var assetMessage = AssetLogMessage.From(null, assetItem.ToReference(), message, assetFullPath); // Forward log messages to compilationResult compilationResult.Log(assetMessage); // Forward log messages to build step logger resultPerAssetType.BuildSteps.Logger.Log(assetMessage); } // Make the build step fail if there was an error during compiling (only when we are compiling the build steps of an asset) if (resultPerAssetType.BuildSteps is AssetBuildStep && resultPerAssetType.BuildSteps.Logger.HasErrors) { resultPerAssetType.BuildSteps.Add(new CommandBuildStep(new FailedCommand(assetItem.Location))); } // TODO: Big review of the log infrastructure of CompilerApp & BuildEngine! // Assign module string to all command build steps SetAssetLogger(resultPerAssetType.BuildSteps, assetItem.Package, assetItem.ToReference(), assetItem.FullPath.ToWindowsPath()); foreach (var buildStep in resultPerAssetType.BuildSteps) { buildStep.Priority = latestPriority++; } // Add the item result build steps the item list result build steps return(resultPerAssetType.BuildSteps); } catch (Exception ex) { compilationResult.Error($"Unexpected exception while compiling asset [{assetItem.Id}] from path [{assetItem.Location}]", ex); return(null); } }
/// <summary> /// Compiles the asset from the specified package. /// </summary> /// <param name="context">The context to use to compile the asset.</param> /// <param name="assetItem">The asset to compile</param> /// <param name="targetUrlInStorage">The absolute URL to the asset, relative to the storage.</param> /// <param name="result">The result where the commands and logs should be output.</param> protected abstract void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result);
/// <summary> /// Generate the build step corresponding to raw imports of the current package file. /// </summary> /// <param name="context">The compilation context</param> /// <param name="result">The compilation current result</param> private void GenerateRawImportBuildSteps(AssetCompilerContext context, AssetCompilerResult result) { if (context.Package.RootDirectory == null) return; foreach (var profile in context.Package.Profiles) { foreach (var sourceFolder in profile.AssetFolders) { var baseDirectory = Path.GetFullPath(context.Package.RootDirectory); // Use sub directory baseDirectory = Path.Combine(baseDirectory, sourceFolder.Path); if (!Directory.Exists(baseDirectory)) { continue; } var baseUDirectory = new UDirectory(baseDirectory); var hashSet = new HashSet<string>(); // Imports explicit foreach (var rawImport in sourceFolder.RawImports) { var sourceDirectory = baseUDirectory; if (!string.IsNullOrEmpty(rawImport.SourceDirectory)) sourceDirectory = UPath.Combine(sourceDirectory, rawImport.SourceDirectory); if (!Directory.Exists(sourceDirectory)) { result.Error("Unable to find raw import directory [{0}]", sourceDirectory); continue; } var files = Directory.EnumerateFiles(sourceDirectory, "*.*", SearchOption.AllDirectories).ToList(); var importRegexes = rawImport.Patterns.Select(x => new Regex(Selectors.PathSelector.TransformToRegex(x))).ToArray(); foreach (var file in files) { var pathToFileRelativeToProject = new UFile(file).MakeRelative(sourceDirectory); var outputPath = pathToFileRelativeToProject; if (!string.IsNullOrEmpty(rawImport.TargetLocation)) outputPath = UPath.Combine(rawImport.TargetLocation, outputPath); foreach (var importRegex in importRegexes) { if (importRegex.Match(pathToFileRelativeToProject).Success && hashSet.Add(outputPath)) { result.BuildSteps.Add(new ImportStreamCommand { SourcePath = file, Location = outputPath, }); break; } } } } } } }
/// <summary> /// Compiles the asset from the specified package. /// </summary> /// <param name="context">The context to use to compile the asset.</param> /// <param name="assetItem">The asset to compile</param> /// <param name="targetUrlInStorage">The absolute URL to the asset, relative to the storage.</param> /// <param name="result">The result where the commands and logs should be output.</param> protected abstract void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result);
public EffectLogBuildStep(AssetCompilerContext context, UFile originalSourcePath, AssetItem assetItem) { this.context = context; this.originalSourcePath = originalSourcePath; this.assetItem = assetItem; }
public AssetCompilerResult Compile(AssetCompilerContext context) { var result = new AssetCompilerResult(); var package = context.Package; // Sort the items to build by build order var assets = package.Assets.ToList(); assets.Sort((item1, item2) => item1.Asset != null && item2.Asset != null ? item1.Asset.InternalBuildOrder.CompareTo(item2.Asset.InternalBuildOrder) : 0); // generate the build steps required to build the assets via base class Compile(context, assets, result); return result; }
public static BuildStep FromRequest(AssetCompilerContext context, Package package, UDirectory urlRoot, EffectCompileRequest effectCompileRequest) { var compilerParameters = new CompilerParameters(effectCompileRequest.UsedParameters); compilerParameters.EffectParameters.Platform = context.GetGraphicsPlatform(package); compilerParameters.EffectParameters.Profile = context.GetGameSettingsAsset().Get<RenderingSettings>(context.Platform).DefaultGraphicsProfile; compilerParameters.EffectParameters.ApplyCompilationMode(context.GetCompilationMode()); return new CommandBuildStep(new EffectCompileCommand(context, urlRoot, effectCompileRequest.EffectName, compilerParameters, package)); }
/// <summary> /// Compile the current package and all child package recursively by generating a list of build steps /// </summary> private void RecursiveCompile(AssetCompilerResult result, AssetCompilerContext context, HashSet<Package> processed) { if (result == null) throw new ArgumentNullException("result"); if (context == null) throw new ArgumentNullException("context"); if (context.Package == null) throw new ArgumentException("context.Package cannot be null", "context"); if (processed.Contains(context.Package)) { return; } processed.Add(context.Package); var package = context.Package; var session = package.Session; // 1. first recursively process all store packages foreach (var packageDependency in package.Meta.Dependencies) { var subPackage = session.Packages.Find(packageDependency); if (subPackage != null) { // Work on an immutable copy for the whole set of assets to compile var contextCopy = (AssetCompilerContext)context.Clone(); contextCopy.Package = subPackage; RecursiveCompile(result, contextCopy, processed); } else { result.Error("Unable to find package [{0}]", packageDependency); } } // 2. recursively process all local packages foreach (var subPackageReference in package.LocalDependencies) { var subPackage = session.Packages.Find(subPackageReference.Id); if (subPackage != null) { // Work on an immutable copy for the whole set of assets to compile var contextCopy = (AssetCompilerContext)context.Clone(); contextCopy.Package = subPackage; RecursiveCompile(result, contextCopy, processed); } else { result.Error("Unable to find package [{0}]", subPackageReference); } } result.Info("Compiling package [{0}]", package.FullPath); // Compile using all PackageCompiler foreach (var compiler in compilers) { var compilerResult = compiler.Compile(context); compilerResult.CopyTo(result); while (compilerResult.BuildSteps.Count > 0) { var step = compilerResult.BuildSteps[0]; compilerResult.BuildSteps.RemoveAt(0); result.BuildSteps.Add(step); } } }
public CompileDefaultSceneEffectCommand(AssetCompilerContext context, Package package, AssetCompilerResult compilerResult) { this.context = context; this.package = package; this.compilerResult = compilerResult; }
public AssetCompilerResult Compile(AssetCompilerContext context) { var result = new AssetCompilerResult(); // generate the build steps required to build the assets via base class Compile(context, assets, result); return result; }
/// <summary> /// Compiles the given asset with its dependencies. /// </summary> /// <param name="context">The asset compiler context.</param> /// <param name="assetItem">The asset to compile with its dependencies.</param> /// <param name="originalItem"></param> /// <param name="compilationResult">The result of the compilation.</param> protected virtual void CompileWithDependencies(AssetCompilerContext context, AssetItem assetItem, AssetItem originalItem, AssetCompilerResult compilationResult) { CompilePackage(context, compilationResult); }
private BuildResultCode BuildMaster() { // Only querying graphics platform, let's load package, print it and exit if (builderOptions.GetGraphicsPlatform) { return BuildGetGraphicsPlatform(); } assetLogger = new RemoteLogForwarder(builderOptions.Logger, builderOptions.LogPipeNames); GlobalLogger.GlobalMessageLogged += assetLogger; PackageSession projectSession = null; try { // TODO handle solution file + package-id ? // When the current platform is not on windows, we need to make sure that all plugins are build, so we // setup auto-compile when loading the session var sessionLoadParameters = new PackageLoadParameters { AutoCompileProjects = builderOptions.Platform != PlatformType.Windows || !builderOptions.DisableAutoCompileProjects, ExtraCompileProperties = builderOptions.ExtraCompileProperties, }; // Loads the root Package var projectSessionResult = PackageSession.Load(builderOptions.PackageFile, sessionLoadParameters); if (projectSessionResult.HasErrors) { projectSessionResult.CopyTo(builderOptions.Logger); return BuildResultCode.BuildError; } projectSession = projectSessionResult.Session; // Check build configuration var package = projectSession.LocalPackages.Last(); // Check build profile var sharedProfile = package.Profiles.FindSharedProfile(); var buildProfile = package.Profiles.FirstOrDefault(pair => pair.Name == builderOptions.BuildProfile); if (buildProfile == null) { builderOptions.Logger.Error("Unable to find profile [{0}] in package [{1}]", builderOptions.BuildProfile, package.FullPath); return BuildResultCode.BuildError; } // Setup variables var buildDirectory = builderOptions.BuildDirectory; var outputDirectory = builderOptions.OutputDirectory; // Process game settings asset var gameSettingsAsset = package.GetGameSettingsAsset(); if (gameSettingsAsset == null) { builderOptions.Logger.Warning("Could not find game settings asset at location [{0}]. Use a Default One", GameSettingsAsset.GameSettingsLocation); gameSettingsAsset = new GameSettingsAsset(); } // Create context var context = new AssetCompilerContext { Profile = builderOptions.BuildProfile, Platform = builderOptions.Platform }; context.SetGameSettingsAsset(gameSettingsAsset); // Copy properties from shared profiles to context properties if (sharedProfile != null) { sharedProfile.Properties.CopyTo(context.PackageProperties, true); } // Copy properties from build profile buildProfile.Properties.CopyTo(context.PackageProperties, true); // Builds the project var assetBuilder = new PackageCompiler(new RootPackageAssetEnumerator(package)); assetBuilder.AssetCompiled += RegisterBuildStepProcessedHandler; var assetBuildResult = assetBuilder.Compile(context); assetBuildResult.CopyTo(builderOptions.Logger); if (assetBuildResult.HasErrors) return BuildResultCode.BuildError; // Create the builder var indexName = "index." + builderOptions.BuildProfile; builder = new Builder(buildDirectory, builderOptions.BuildProfile, indexName, builderOptions.Logger) { ThreadCount = builderOptions.ThreadCount }; builder.MonitorPipeNames.AddRange(builderOptions.MonitorPipeNames); // Add build steps generated by AssetBuilder builder.Root.Add(assetBuildResult.BuildSteps); // Run builder var result = builder.Run(Builder.Mode.Build); builder.WriteIndexFile(false); // Fill list of bundles var bundlePacker = new BundlePacker(); bundlePacker.Build(builderOptions.Logger, projectSession, buildProfile, indexName, outputDirectory, builder.DisableCompressionIds); return result; } finally { if (builder != null) { builder.Dispose(); } // Dispose the session (in order to unload assemblies) if (projectSession != null) { projectSession.Dispose(); } // Flush and close logger GlobalLogger.GlobalMessageLogged -= assetLogger; assetLogger.Dispose(); } }
/// <summary> /// Compile the current package and all child package recursively by generating a list of build steps /// </summary> private void RecursiveCompile(AssetCompilerResult result, AssetCompilerContext context, HashSet <Package> processed) { if (result == null) { throw new ArgumentNullException("result"); } if (context == null) { throw new ArgumentNullException("context"); } if (context.Package == null) { throw new ArgumentException("context.Package cannot be null", "context"); } if (processed.Contains(context.Package)) { return; } processed.Add(context.Package); var package = context.Package; var session = package.Session; // 1. first recursively process all store packages foreach (var packageDependency in package.Meta.Dependencies) { var subPackage = session.Packages.Find(packageDependency); if (subPackage != null) { // Work on an immutable copy for the whole set of assets to compile var contextCopy = (AssetCompilerContext)context.Clone(); contextCopy.Package = subPackage; RecursiveCompile(result, contextCopy, processed); } else { result.Error("Unable to find package [{0}]", packageDependency); } } // 2. recursively process all local packages foreach (var subPackageReference in package.LocalDependencies) { var subPackage = session.Packages.Find(subPackageReference.Id); if (subPackage != null) { // Work on an immutable copy for the whole set of assets to compile var contextCopy = (AssetCompilerContext)context.Clone(); contextCopy.Package = subPackage; RecursiveCompile(result, contextCopy, processed); } else { result.Error("Unable to find package [{0}]", subPackageReference); } } result.Info("Compiling package [{0}]", package.FullPath); // Compile using all PackageCompiler foreach (var compiler in compilers) { var compilerResult = compiler.Compile(context); compilerResult.CopyTo(result); while (compilerResult.BuildSteps.Count > 0) { var step = compilerResult.BuildSteps[0]; compilerResult.BuildSteps.RemoveAt(0); result.BuildSteps.Add(step); } } }