예제 #1
0
        private void AddDependencies(AssetItem assetItem, HashSet <BuildDependencyInfo> typesToInclude, HashSet <Type> typesToExclude)
        {
            // for now we use the dependency manager itself to resolve runtime dependencies, in the future we might want to unify the builddependency manager with the dependency manager
            var dependencies = assetItem.Package.Session.DependencyManager.ComputeDependencies(assetItem.Id, AssetDependencySearchOptions.Out);

            if (dependencies != null)
            {
                foreach (var assetDependency in dependencies.LinksOut)
                {
                    var assetType = assetDependency.Item.Asset.GetType();
                    if (!typesToExclude.Contains(assetType)) //filter out what we do not need
                    {
                        foreach (var input in typesToInclude.Where(x => x.AssetType == assetType))
                        {
                            var node = buildDependencyManager.FindOrCreateNode(assetDependency.Item, input.CompilationContext);
                            var link = new BuildAssetLink(this, node, input.DependencyType);
                            references.TryAdd(link, link);
                            if (link.HasOne(BuildDependencyType.CompileAsset))
                            {
                                // When we have a CompileAsset type of dependency, we want to analyze this asset and extract other assets that it references and are needed by this asset.
                                AddDependencies(assetDependency.Item, typesToInclude, typesToExclude);
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Performs analysis on the asset to figure out all the needed dependencies
        /// </summary>
        /// <param name="context">The compiler context</param>
        /// <returns>True if the node was updated, false otherwise.</returns>
        public bool Analyze(AssetCompilerContext context)
        {
            var assetVersion = AssetItem.Version;

            if (Interlocked.Exchange(ref version, assetVersion) == assetVersion)
            {
                // This node is up-to-date. Let's check if CompileAsset links are also up-to-date.
                // Otherwise we need to refresh this node since this kind of link can bring additional dependencies.
                var upToDate = true;
                foreach (var node in References)
                {
                    if (node.HasOne(BuildDependencyType.CompileAsset))
                    {
                        if (node.Target.Analyze(context))
                        {
                            upToDate = false;
                        }
                    }
                }

                if (upToDate)
                {
                    return(false); // Same version, skip analysis, do not clear links
                }
            }

            var mainCompiler = BuildDependencyManager.AssetCompilerRegistry.GetCompiler(AssetItem.Asset.GetType(), CompilationContext);

            if (mainCompiler == null)
            {
                return(false); // Scripts and such don't have compiler
            }
            var typesToInclude = new HashSet <BuildDependencyInfo>(mainCompiler.GetInputTypes(AssetItem));
            var typesToExclude = new HashSet <Type>(mainCompiler.GetInputTypesToExclude(AssetItem));

            // Clean up our references
            references.Clear();

            // DependencyManager check
            AddDependencies(AssetItem, typesToInclude, typesToExclude);

            // Input files required
            foreach (var inputFile in new HashSet <ObjectUrl>(mainCompiler.GetInputFiles(AssetItem))) //directly resolve by input files, in the future we might just want this pass
            {
                if (inputFile.Type == UrlType.Content)
                {
                    var asset = AssetItem.Package.Session.FindAsset(inputFile.Path); //this will search all packages
                    if (asset == null)
                    {
                        continue; //this might be an error tho... but in the end compilation might fail so we let the build engine do the error reporting if it really was a issue
                    }
                    if (!typesToExclude.Contains(asset.GetType()))
                    {
                        // TODO: right now, we consider that assets returned by GetInputFiles must be compiled in AssetCompilationContext. At some point, we might need to be able to specify a custom context.
                        var dependencyType = inputFile.Type == UrlType.Content ? BuildDependencyType.CompileContent : BuildDependencyType.CompileAsset; //Content means we need to load the content, the rest is just asset dependency
                        var node           = buildDependencyManager.FindOrCreateNode(asset, typeof(AssetCompilationContext));
                        var link           = new BuildAssetLink(this, node, dependencyType);
                        references.TryAdd(link, link);
                    }
                }
            }

            bool shouldVisitTypes;

            context.Properties.TryGet(VisitRuntimeTypes, out shouldVisitTypes);
            if (shouldVisitTypes || mainCompiler.AlwaysCheckRuntimeTypes)
            {
                var collector = new RuntimeDependenciesCollector(mainCompiler.GetRuntimeTypes(AssetItem));
                var deps      = collector.GetDependencies(AssetItem);
                foreach (var reference in deps)
                {
                    var asset = AssetItem.Package.FindAsset(reference.Id);
                    if (asset != null)
                    {
                        // TODO: right now, we consider that assets found with RuntimeDependenciesCollector must be compiled in AssetCompilationContext. At some point, we might need to be able to specify a custom context.
                        var dependencyType = BuildDependencyType.Runtime;
                        var node           = buildDependencyManager.FindOrCreateNode(asset, typeof(AssetCompilationContext));
                        var link           = new BuildAssetLink(this, node, dependencyType);
                        references.TryAdd(link, link);
                    }
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Performs analysis on the asset to figure out all the needed dependencies
        /// </summary>
        /// <param name="context">The compiler context</param>
        public void Analyze(AssetCompilerContext context)
        {
            var assetVersion = AssetItem.Version;

            if (Interlocked.Exchange(ref version, assetVersion) == assetVersion)
            {
                return; //same version, skip analysis, do not clear links
            }
            var mainCompiler = BuildDependencyManager.AssetCompilerRegistry.GetCompiler(AssetItem.Asset.GetType(), CompilationContext);

            if (mainCompiler == null)
            {
                return; //scripts and such don't have compiler
            }
            var typesToInclude = new HashSet <BuildDependencyInfo>(mainCompiler.GetInputTypes(AssetItem));
            var typesToExclude = new HashSet <Type>(mainCompiler.GetInputTypesToExclude(AssetItem));

            //clean up our references
            references.Clear();

            //DependencyManager check
            //for now we use the dependency manager itself to resolve runtime dependencies, in the future we might want to unify the builddependency manager with the dependency manager
            var dependencies = AssetItem.Package.Session.DependencyManager.ComputeDependencies(AssetItem.Id, AssetDependencySearchOptions.Out);

            if (dependencies != null)
            {
                foreach (var assetDependency in dependencies.LinksOut)
                {
                    var assetType = assetDependency.Item.Asset.GetType();
                    if (!typesToExclude.Contains(assetType)) //filter out what we do not need
                    {
                        foreach (var input in typesToInclude.Where(x => x.AssetType == assetType))
                        {
                            var node = buildDependencyManager.FindOrCreateNode(assetDependency.Item, input.CompilationContext);
                            var link = new BuildAssetLink(this, node, input.DependencyType);
                            references.TryAdd(link, link);
                        }
                    }
                }
            }

            //Input files required
            foreach (var inputFile in new HashSet <ObjectUrl>(mainCompiler.GetInputFiles(AssetItem))) //directly resolve by input files, in the future we might just want this pass
            {
                if (inputFile.Type == UrlType.Content || inputFile.Type == UrlType.ContentLink)
                {
                    var asset = AssetItem.Package.Session.FindAsset(inputFile.Path); //this will search all packages
                    if (asset == null)
                    {
                        continue; //this might be an error tho... but in the end compilation might fail so we let the build engine do the error reporting if it really was a issue
                    }
                    if (!typesToExclude.Contains(asset.GetType()))
                    {
                        // TODO: right now, we consider that assets returned by GetInputFiles must be compiled in AssetCompilationContext. At some point, we might need to be able to specify a custom context.
                        var dependencyType = inputFile.Type == UrlType.Content ? BuildDependencyType.CompileContent : BuildDependencyType.CompileAsset; //Content means we need to load the content, the rest is just asset dependency
                        var node           = buildDependencyManager.FindOrCreateNode(asset, typeof(AssetCompilationContext));
                        var link           = new BuildAssetLink(this, node, dependencyType);
                        references.TryAdd(link, link);
                    }
                }
            }

            bool shouldVisitTypes;

            context.Properties.TryGet(VisitRuntimeTypes, out shouldVisitTypes);
            if (shouldVisitTypes || mainCompiler.AlwaysCheckRuntimeTypes)
            {
                var collector = new RuntimeDependenciesCollector(mainCompiler.GetRuntimeTypes(AssetItem));
                var deps      = collector.GetDependencies(AssetItem);
                foreach (var reference in deps)
                {
                    var asset = AssetItem.Package.FindAsset(reference.Id);
                    if (asset != null)
                    {
                        // TODO: right now, we consider that assets found with RuntimeDependenciesCollector must be compiled in AssetCompilationContext. At some point, we might need to be able to specify a custom context.
                        var dependencyType = BuildDependencyType.Runtime;
                        var node           = buildDependencyManager.FindOrCreateNode(asset, typeof(AssetCompilationContext));
                        var link           = new BuildAssetLink(this, node, dependencyType);
                        references.TryAdd(link, link);
                    }
                }
            }
        }