Exemple #1
0
        /// <summary>
        /// Ensures that the sources of an <see cref="Asset"/> exist.
        /// </summary>
        /// <param name="result">The <see cref="AssetCompilerResult"/> in which to output log of potential errors.</param>
        /// <param name="assetItem">The asset to check.</param>
        /// <returns><c>true</c> if the source file exists, <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">Any of the argument is <c>null</c>.</exception>
        private static bool EnsureSourcesExist(AssetCompilerResult result, AssetItem assetItem)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }
            if (assetItem == null)
            {
                throw new ArgumentNullException(nameof(assetItem));
            }

            var collector     = new SourceFilesCollector();
            var sourceMembers = collector.GetSourceMembers(assetItem.Asset);

            foreach (var member in sourceMembers)
            {
                if (string.IsNullOrEmpty(member.Value))
                {
                    result.Error($"Source is null for Asset [{assetItem}] in property [{member.Key}]");
                    return(false);
                }

                // Get absolute path of asset source on disk
                var assetDirectory = assetItem.FullPath.GetParent();
                var assetSource    = UPath.Combine(assetDirectory, member.Value);

                // Ensure the file exists
                if (!File.Exists(assetSource))
                {
                    result.Error($"Unable to find the source file '{assetSource}' for Asset [{assetItem}]");
                    return(false);
                }
            }

            return(true);
        }
        private void Prepare(AssetCompilerResult finalResult, AssetCompilerContext context, AssetItem assetItem, [NotNull] Type compilationContext, HashSet <BuildAssetNode> visitedItems, Dictionary <AssetId, BuildStep> compiledItems, BuildStep parentBuildStep = null,
                             BuildDependencyType dependencyType = BuildDependencyType.Runtime)
        {
            if (compilationContext == null)
            {
                throw new ArgumentNullException(nameof(compilationContext));
            }
            var assetNode = BuildDependencyManager.FindOrCreateNode(assetItem, compilationContext);

            compiledItems.TryGetValue(assetNode.AssetItem.Id, out var assetBuildSteps);

            // Prevent re-entrancy in the same node
            if (visitedItems.Add(assetNode))
            {
                assetNode.Analyze(context);

                // Invoke the compiler to prepare the build step for this asset if the dependency needs to compile it (Runtime or CompileContent)
                if ((dependencyType & ~BuildDependencyType.CompileAsset) != 0 && assetBuildSteps == null)
                {
                    var mainCompiler = BuildDependencyManager.AssetCompilerRegistry.GetCompiler(assetItem.Asset.GetType(), assetNode.CompilationContext);
                    if (mainCompiler == null)
                    {
                        return;
                    }

                    var compilerResult = mainCompiler.Prepare(context, assetItem);

                    if ((dependencyType & BuildDependencyType.Runtime) == BuildDependencyType.Runtime && compilerResult.HasErrors) //allow Runtime dependencies to fail
                    {
                        assetBuildSteps = new ErrorBuildStep(assetItem, compilerResult.Messages);
                    }
                    else
                    {
                        assetBuildSteps = compilerResult.BuildSteps;
                        compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);

                        // Copy the log to the final result (note: this does not copy or forward the build steps)
                        compilerResult.CopyTo(finalResult);
                        if (compilerResult.HasErrors)
                        {
                            finalResult.Error($"Failed to prepare asset {assetItem.Location}");
                            return;
                        }
                    }

                    // Add the resulting build steps to the final
                    finalResult.BuildSteps.Add(assetBuildSteps);

                    AssetCompiled?.Invoke(this, new AssetCompiledArgs(assetItem, compilerResult));
                }

                // Go through the dependencies of the node and prepare them as well
                foreach (var reference in assetNode.References)
                {
                    var target = reference.Target;
                    Prepare(finalResult, context, target.AssetItem, target.CompilationContext, visitedItems, compiledItems, assetBuildSteps, reference.DependencyType);
                    if (finalResult.HasErrors)
                    {
                        return;
                    }
                }

                // If we didn't prepare any build step for this asset let's exit here.
                if (assetBuildSteps == null)
                {
                    return;
                }
            }

            // Link the created build steps to their parent step.
            if (parentBuildStep != null && assetBuildSteps != null && (dependencyType & BuildDependencyType.CompileContent) == BuildDependencyType.CompileContent) //only if content is required Content.Load
            {
                BuildStep.LinkBuildSteps(assetBuildSteps, parentBuildStep);
            }
        }
Exemple #3
0
        /// <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);
            }
        }