예제 #1
0
        /// <summary>
        /// Overrides base class to add module runtime dependencies to the build receipt.
        /// </summary>
        /// <param name="ToolChain">The platform toolchain</param>
        public override BuildReceipt MakeReceipt(IUEToolChain ToolChain)
        {
            BuildReceipt Receipt = base.MakeReceipt(ToolChain);

            // Set the IsPrecompiled flag on all the build products if we're not actually building this binary
            if (!Config.bAllowCompilation)
            {
                foreach (BuildProduct BuildProduct in Receipt.BuildProducts)
                {
                    BuildProduct.IsPrecompiled = true;
                }
            }

            // Add the compiled resource file if we're building a static library containing the launch module on Windows
            if (Config.Type == UEBuildBinaryType.StaticLibrary && ModuleNames.Contains("Launch") && (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64))
            {
                string ResourceFilePath = Path.Combine(Config.IntermediateDirectory, "Launch", "PCLaunch.rc.res");
                Receipt.AddBuildProduct(ResourceFilePath, BuildProductType.StaticLibrary);
            }

            // Add runtime dependencies for all the modules in this binary, and build up a list of all the referenced modules
            var ReferencedModules = new CaselessDictionary <UEBuildModule.ModuleIndexPair>();

            foreach (string ModuleName in ModuleNames)
            {
                UEBuildModule Module = Target.GetModuleByName(ModuleName);
                foreach (RuntimeDependency RuntimeDependency in Module.RuntimeDependencies)
                {
                    Receipt.RuntimeDependencies.Add(new RuntimeDependency(RuntimeDependency));
                }
                Module.GetAllDependencyModules(ReferencedModules, true, false, true);
            }

            // Add runtime dependencies for all the referenced external modules. These may be introduce dependencies for the binary without actually being listed for inclusion in it.
            foreach (UEBuildExternalModule ExternalModule in ReferencedModules.Values.OrderBy(x => x.Index).Select(x => x.Module).OfType <UEBuildExternalModule>())
            {
                foreach (RuntimeDependency RuntimeDependency in ExternalModule.RuntimeDependencies)
                {
                    Receipt.RuntimeDependencies.Add(new RuntimeDependency(RuntimeDependency));
                }
            }
            return(Receipt);
        }
예제 #2
0
        /// <summary>
        /// Generates a list of all modules referenced by this binary
        /// </summary>
        /// <param name="bIncludeDynamicallyLoaded">True if dynamically loaded modules (and all of their dependent modules) should be included.</param>
        /// <param name="bForceCircular">True if circular dependencies should be process</param>
        /// <returns>List of all referenced modules</returns>
        public override List <UEBuildModule> GetAllDependencyModules(bool bIncludeDynamicallyLoaded, bool bForceCircular)
        {
            var ReferencedModules = new CaselessDictionary <UEBuildModule.ModuleIndexPair>();

            foreach (var ModuleName in ModuleNames)
            {
                if (!ReferencedModules.ContainsKey(ModuleName))
                {
                    var Module = Target.GetModuleByName(ModuleName);
                    ReferencedModules[ModuleName] = null;

                    Module.GetAllDependencyModules(ReferencedModules, bIncludeDynamicallyLoaded, bForceCircular, bOnlyDirectDependencies: false);

                    ReferencedModules[ModuleName] = new UEBuildModule.ModuleIndexPair {
                        Module = Module, Index = ReferencedModules.Count
                    };
                }
            }

            return(ReferencedModules.Values.OrderBy(M => M.Index).Select(M => M.Module).ToList());
        }
예제 #3
0
        // UEBuildModule interface.
        public override List<FileItem> Compile(CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment)
        {
            var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

            var LinkInputFiles = new List<FileItem>();
            if( ProjectFileGenerator.bGenerateProjectFiles && IntelliSenseGatherer == null)
            {
                // Nothing to do for IntelliSense, bail out early
                return LinkInputFiles;
            }

            var ModuleCompileEnvironment = CreateModuleCompileEnvironment(CompileEnvironment);
            IncludeSearchPaths = ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths.ToList();
            IncludeSearchPaths.AddRange(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.ToList());

            if( IntelliSenseGatherer != null )
            {
                // Update project file's set of preprocessor definitions and include paths
                IntelliSenseGatherer.AddIntelliSensePreprocessorDefinitions( ModuleCompileEnvironment.Config.Definitions );
                IntelliSenseGatherer.AddInteliiSenseIncludePaths( ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, bAddingSystemIncludes: true );
                IntelliSenseGatherer.AddInteliiSenseIncludePaths( ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, bAddingSystemIncludes: false );

                // Bail out.  We don't need to actually compile anything while generating project files.
                return LinkInputFiles;
            }

            // Throw an error if the module's source file list referenced any non-existent files.
            if (SourceFilesToBuild.MissingFiles.Count > 0)
            {
                throw new BuildException(
                    "UBT ERROR: Module \"{0}\" references non-existent files:\n{1} (perhaps a file was added to the project but not checked in)",
                    Name,
                    string.Join("\n", SourceFilesToBuild.MissingFiles.Select(M => M.AbsolutePath))
                );
            }

            // For an executable or a static library do not use the default RC file -
            // If the executable wants it, it will be in their source list anyway.
            // The issue here is that when making a monolithic game, the processing
            // of the other game modules will stomp the game-specific rc file.
            if (Binary.Config.Type == UEBuildBinaryType.DynamicLinkLibrary)
            {
                // Add default PCLaunch.rc file if this module has no own resource file specified
                if (SourceFilesToBuild.RCFiles.Count <= 0)
                {
                    string DefRC = Utils.CleanDirectorySeparators( Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Launch/Resources/Windows/PCLaunch.rc")) );
                    FileItem Item = FileItem.GetItemByFullPath(DefRC);
                    SourceFilesToBuild.RCFiles.Add(Item);
                }

                // Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions.
                string ModuleVersionRC = Utils.CleanDirectorySeparators( Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "Runtime/Core/Resources/Windows/ModuleVersionResource.rc.inl")) );
                FileItem ModuleVersionItem = FileItem.GetItemByFullPath(ModuleVersionRC);
                if( !SourceFilesToBuild.RCFiles.Contains(ModuleVersionItem) )
                {
                    SourceFilesToBuild.RCFiles.Add(ModuleVersionItem);
                }
            }

            {
                // Process all of the header file dependencies for this module
                this.CachePCHUsageForModuleSourceFiles( ModuleCompileEnvironment );

                // Make sure our RC files have cached includes.
                foreach( var RCFile in SourceFilesToBuild.RCFiles )
                {
                    RCFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
                }
            }

            // Check to see if this is an Engine module (including program or plugin modules).  That is, the module is located under the "Engine" folder
            var IsGameModule = !Utils.IsFileUnderDirectory( this.ModuleDirectory, Path.Combine( ProjectFileGenerator.EngineRelativePath ) );

            // Should we force a precompiled header to be generated for this module?  Usually, we only bother with a
            // precompiled header if there are at least several source files in the module (after combining them for unity
            // builds.)  But for game modules, it can be convenient to always have a precompiled header to single-file
            // changes to code is really quick to compile.
            int MinFilesUsingPrecompiledHeader = BuildConfiguration.MinFilesUsingPrecompiledHeader;
            if( MinFilesUsingPrecompiledHeaderOverride != 0 )
            {
                MinFilesUsingPrecompiledHeader = MinFilesUsingPrecompiledHeaderOverride;
            }
            else if( IsGameModule && BuildConfiguration.bForcePrecompiledHeaderForGameModules )
            {
                // This is a game module with only a small number of source files, so go ahead and force a precompiled header
                // to be generated to make incremental changes to source files as fast as possible for small projects.
                MinFilesUsingPrecompiledHeader = 1;
            }

            // Should we use unity build mode for this module?
            bool bModuleUsesUnityBuild = BuildConfiguration.bUseUnityBuild || BuildConfiguration.bForceUnityBuild;
            if (!BuildConfiguration.bForceUnityBuild)
            {
                if (bFasterWithoutUnity)
                {
                    bModuleUsesUnityBuild = false;
                }
                else if (IsGameModule && SourceFilesToBuild.CPPFiles.Count < BuildConfiguration.MinGameModuleSourceFilesForUnityBuild)
                {
                    // Game modules with only a small number of source files are usually better off having faster iteration times
                    // on single source file changes, so we forcibly disable unity build for those modules
                    bModuleUsesUnityBuild = false;
                }
            }

            // The environment with which to compile the CPP files
            var CPPCompileEnvironment = ModuleCompileEnvironment;

            // Precompiled header support.
            bool bWasModuleCodeCompiled = false;
            if (BuildPlatform.ShouldUsePCHFiles(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration))
            {
                var PCHGenTimerStart = DateTime.UtcNow;

                // The code below will figure out whether this module will either use a "unique PCH" (private PCH that will only be included by
                // this module's code files), or a "shared PCH" (potentially included by many code files in many modules.)  Only one or the other
                // will be used.
                FileItem SharedPCHHeaderFile = null;

                // In the case of a shared PCH, we also need to keep track of which module that PCH's header file is a member of
                string SharedPCHModuleName = String.Empty;

                if( BuildConfiguration.bUseSharedPCHs && CompileEnvironment.Config.bIsBuildingLibrary )
                {
                    Log.TraceVerbose("Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library", this.Name );
                }

                bool bUseSharedPCHFiles  = BuildConfiguration.bUseSharedPCHs && !CompileEnvironment.Config.bIsBuildingLibrary && GlobalCompileEnvironment.SharedPCHHeaderFiles.Count > 0;

                if( bUseSharedPCHFiles )
                {
                    string SharingPCHHeaderFilePath = null;
                    bool bIsASharedPCHModule = bUseSharedPCHFiles && GlobalCompileEnvironment.SharedPCHHeaderFiles.Any( PCH => PCH.Module == this );
                    if( bIsASharedPCHModule )
                    {
                        SharingPCHHeaderFilePath = Path.GetFullPath( Path.Combine( ProjectFileGenerator.RootRelativePath, "Engine", "Source", this.SharedPCHHeaderFile ) );
                    }

                    // We can't use a shared PCH file when compiling a module
                    // with exports, because the shared PCH can only have imports in it to work correctly.
                    bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH && bIsASharedPCHModule && !Binary.Config.bAllowExports && ProcessedDependencies.UniquePCHHeaderFile.AbsolutePath.Equals( SharingPCHHeaderFilePath, StringComparison.InvariantCultureIgnoreCase );
                    if( bAllowSharedPCH && ( !bIsASharedPCHModule || bCanModuleUseOwnSharedPCH ) )
                    {
                        // Figure out which shared PCH tier we're in
                        var ReferencedModules = new CaselessDictionary<ModuleIndexPair>();
                        {
                            this.GetAllDependencyModules( ReferencedModules, bIncludeDynamicallyLoaded:false, bForceCircular:false, bOnlyDirectDependencies:true );
                        }

                        int LargestSharedPCHHeaderFileIndex = -1;
                        foreach( var DependencyModule in ReferencedModules.Values.OrderBy(P => P.Index).Select(P => P.Module) )
                        {
                            // These Shared PCHs are ordered from least complex to most complex.  We'll start at the last one and search backwards.
                            for( var SharedPCHHeaderFileIndex = GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex; --SharedPCHHeaderFileIndex )
                            {
                                var CurSharedPCHHeaderFile = GlobalCompileEnvironment.SharedPCHHeaderFiles[ SharedPCHHeaderFileIndex ];

                                if( DependencyModule == CurSharedPCHHeaderFile.Module ||
                                    ( bIsASharedPCHModule && CurSharedPCHHeaderFile.Module == this ) )	// If we ourselves are a shared PCH module, always at least use our own module as our shared PCH header if we can't find anything better
                                {
                                    SharedPCHModuleName = CurSharedPCHHeaderFile.Module.Name;
                                    SharedPCHHeaderFile = CurSharedPCHHeaderFile.PCHHeaderFile;
                                    LargestSharedPCHHeaderFileIndex = SharedPCHHeaderFileIndex;
                                    break;
                                }
                            }

                            if( LargestSharedPCHHeaderFileIndex == GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1 )
                            {
                                // We've determined that the module is using our most complex PCH header, so we can early-out
                                break;
                            }
                        }

                        // Did we not find a shared PCH header that is being included by this module?  This could happen if the module is not including Core.h, even indirectly.
                        if( String.IsNullOrEmpty( SharedPCHModuleName ) )
                        {
                            throw new BuildException( "Module {0} doesn't use a Shared PCH!  Please add a dependency on a Shared PCH module to this module's dependency list", this.Name);
                        }

                        // Keep track of how many modules make use of this PCH for performance diagnostics
                        var LargestSharedPCHHeader = GlobalCompileEnvironment.SharedPCHHeaderFiles[ LargestSharedPCHHeaderFileIndex ];
                        ++LargestSharedPCHHeader.NumModulesUsingThisPCH;

                    }
                    else
                    {
                        Log.TraceVerbose("Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH", this.Name);
                    }
                }

                // The precompiled header environment for all source files in this module that use a precompiled header, if we even need one
                PrecompileHeaderEnvironment ModulePCHEnvironment = null;

                // If there was one header that was included first by enough C++ files, use it as the precompiled header.
                // Only use precompiled headers for projects with enough files to make the PCH creation worthwhile.
                if( SharedPCHHeaderFile != null || SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader )
                {
                    FileItem PCHToUse;

                    if( SharedPCHHeaderFile != null )
                    {
                        ModulePCHEnvironment = ApplySharedPCH(GlobalCompileEnvironment, CompileEnvironment, ModuleCompileEnvironment, SourceFilesToBuild.CPPFiles, ref SharedPCHHeaderFile);
                        if (ModulePCHEnvironment != null)
                        {
                            // @todo SharedPCH: Ideally we would exhaustively check for a compatible compile environment (definitions, imports/exports, etc)
                            //    Currently, it's possible for the shared PCH to be compiled differently depending on which module UBT happened to have
                            //    include it first during the build phase.  This could create problems with deterministic builds, or turn up compile
                            //    errors unexpectedly due to compile environment differences.
                            Log.TraceVerbose("Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment.ModuleName + ")");
                        }

                        PCHToUse = SharedPCHHeaderFile;
                    }
                    else
                    {
                        PCHToUse = ProcessedDependencies.UniquePCHHeaderFile;
                    }

                    if (PCHToUse != null)
                    {
                        // Update all CPPFiles to point to the PCH
                        foreach (var CPPFile in SourceFilesToBuild.CPPFiles)
                        {
                            CPPFile.PCHHeaderNameInCode              = PCHToUse.AbsolutePath;
                            CPPFile.PrecompiledHeaderIncludeFilename = PCHToUse.AbsolutePath;
                        }
                    }

                    // A shared PCH was not already set up for us, so set one up.
                    if( ModulePCHEnvironment == null )
                    {
                        var PCHHeaderFile = ProcessedDependencies.UniquePCHHeaderFile;
                        var PCHModuleName = this.Name;
                        if( SharedPCHHeaderFile != null )
                        {
                            PCHHeaderFile = SharedPCHHeaderFile;
                            PCHModuleName = SharedPCHModuleName;
                        }
                        var PCHHeaderNameInCode = SourceFilesToBuild.CPPFiles[ 0 ].PCHHeaderNameInCode;

                        ModulePCHEnvironment = new PrecompileHeaderEnvironment( PCHModuleName, PCHHeaderNameInCode, PCHHeaderFile, ModuleCompileEnvironment.Config.CLRMode, ModuleCompileEnvironment.Config.OptimizeCode );

                        if( SharedPCHHeaderFile != null )
                        {
                            // Add to list of shared PCH environments
                            GlobalCompileEnvironment.SharedPCHEnvironments.Add( ModulePCHEnvironment );
                            Log.TraceVerbose( "Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'" );
                        }
                        else
                        {
                            Log.TraceVerbose( "Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'" );
                        }
                    }
                }
                else
                {
                    Log.TraceVerbose( "Module " + Name + " doesn't use a Shared PCH, and only has " + SourceFilesToBuild.CPPFiles.Count.ToString() + " source file(s).  No Unique PCH will be generated." );
                }

                // Compile the C++ source or the unity C++ files that use a PCH environment.
                if( ModulePCHEnvironment != null )
                {
                    // Setup a new compile environment for this module's source files.  It's pretty much the exact same as the
                    // module's compile environment, except that it will include a PCH file.

                    var ModulePCHCompileEnvironment = ModuleCompileEnvironment.DeepCopy();
                    ModulePCHCompileEnvironment.Config.PrecompiledHeaderAction          = PrecompiledHeaderAction.Include;
                    ModulePCHCompileEnvironment.Config.PrecompiledHeaderIncludeFilename = ModulePCHEnvironment.PrecompiledHeaderIncludeFilename.AbsolutePath;
                    ModulePCHCompileEnvironment.Config.PCHHeaderNameInCode              = ModulePCHEnvironment.PCHHeaderNameInCode;

                    if( SharedPCHHeaderFile != null )
                    {
                        // Shared PCH headers need to be force included, because we're basically forcing the module to use
                        // the precompiled header that we want, instead of the "first include" in each respective .cpp file
                        ModulePCHCompileEnvironment.Config.bForceIncludePrecompiledHeader = true;
                    }

                    var CPPFilesToBuild = SourceFilesToBuild.CPPFiles;
                    if (bModuleUsesUnityBuild)
                    {
                        // unity files generated for only the set of files which share the same PCH environment
                        CPPFilesToBuild = Unity.GenerateUnityCPPs( Target, CPPFilesToBuild, ModulePCHCompileEnvironment, Name );
                    }

                    // Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one)
                    if( ModulePCHEnvironment.PrecompiledHeaderFile == null )
                    {
                        if( SharedPCHHeaderFile != null || CPPFilesToBuild.Count >= MinFilesUsingPrecompiledHeader )
                        {
                            CPPOutput PCHOutput;
                            if (SharedPCHHeaderFile == null)
                            {
                                PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
                                    Target,
                                    CPPFilesToBuild[0].PCHHeaderNameInCode,
                                    ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
                                    ModuleCompileEnvironment,
                                    ModuleCompileEnvironment.Config.OutputDirectory,
                                    Name,
                                    true );
                            }
                            else
                            {
                                UEBuildModuleCPP SharedPCHModule = (UEBuildModuleCPP)Target.FindOrCreateModuleByName(SharedPCHModuleName);

                                CPPEnvironment SharedPCHCompileEnvironment = GlobalCompileEnvironment.DeepCopy();
                                SharedPCHCompileEnvironment.Config.bEnableShadowVariableWarning = SharedPCHModule.bEnableShadowVariableWarnings;

                                SharedPCHModule.SetupPublicCompileEnvironment(
                                    Binary,
                                    false,
                                    SharedPCHCompileEnvironment.Config.CPPIncludeInfo.IncludePaths,
                                    SharedPCHCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths,
                                    SharedPCHCompileEnvironment.Config.Definitions,
                                    SharedPCHCompileEnvironment.Config.AdditionalFrameworks,
                                    new Dictionary<UEBuildModule,bool>());

                                PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
                                    Target,
                                    CPPFilesToBuild[0].PCHHeaderNameInCode,
                                    ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
                                    SharedPCHCompileEnvironment,
                                    Path.Combine( CompileEnvironment.Config.OutputDirectory, "SharedPCHs" ),
                                    "Shared",
                                    false );
                            }

                            ModulePCHEnvironment.PrecompiledHeaderFile = PCHOutput.PrecompiledHeaderFile;

                            ModulePCHEnvironment.OutputObjectFiles.Clear();
                            ModulePCHEnvironment.OutputObjectFiles.AddRange( PCHOutput.ObjectFiles );
                        }
                        else if( CPPFilesToBuild.Count < MinFilesUsingPrecompiledHeader )
                        {
                            Log.TraceVerbose( "Module " + Name + " doesn't use a Shared PCH, and only has " + CPPFilesToBuild.Count.ToString() + " unity source file(s).  No Unique PCH will be generated." );
                        }
                    }

                    if( ModulePCHEnvironment.PrecompiledHeaderFile != null )
                    {
                        // Link in the object files produced by creating the precompiled header.
                        LinkInputFiles.AddRange( ModulePCHEnvironment.OutputObjectFiles );

                        // if pch action was generated for the environment then use pch
                        ModulePCHCompileEnvironment.PrecompiledHeaderFile = ModulePCHEnvironment.PrecompiledHeaderFile;

                        // Use this compile environment from now on
                        CPPCompileEnvironment = ModulePCHCompileEnvironment;
                    }

                    LinkInputFiles.AddRange( CPPCompileEnvironment.CompileFiles( Target, CPPFilesToBuild, Name ).ObjectFiles );
                    bWasModuleCodeCompiled = true;
                }

                if( BuildConfiguration.bPrintPerformanceInfo )
                {
                    var PCHGenTime = ( DateTime.UtcNow - PCHGenTimerStart ).TotalSeconds;
                    TotalPCHGenTime += PCHGenTime;
                }
            }

            if( !bWasModuleCodeCompiled && SourceFilesToBuild.CPPFiles.Count > 0 )
            {
                var CPPFilesToCompile = SourceFilesToBuild.CPPFiles;
                if (bModuleUsesUnityBuild)
                {
                    CPPFilesToCompile = Unity.GenerateUnityCPPs( Target, CPPFilesToCompile, CPPCompileEnvironment, Name );
                }
                LinkInputFiles.AddRange( CPPCompileEnvironment.CompileFiles( Target, CPPFilesToCompile, Name ).ObjectFiles );
            }

            if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CPPCompileEnvironment.bHackHeaderGenerator)
            {
                string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard));
                foreach (string GeneratedFilename in GeneratedFiles)
                {
                    var GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename);

                    CachePCHUsageForModuleSourceFile(this.Target, CPPCompileEnvironment, GeneratedCppFileItem);

                    // @todo ubtmake: Check for ALL other places where we might be injecting .cpp or .rc files for compiling without caching CachedCPPIncludeInfo first (anything platform specific?)
                    LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles(Target, new List<FileItem> { GeneratedCppFileItem }, Name).ObjectFiles);
                }
            }

            // Compile C files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.CFiles, Name).ObjectFiles);

            // Compile CC files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.CCFiles, Name).ObjectFiles);

            // Compile MM files directly.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileFiles( Target, SourceFilesToBuild.MMFiles, Name).ObjectFiles);

            // Compile RC files.
            LinkInputFiles.AddRange(CPPCompileEnvironment.CompileRCFiles(Target, SourceFilesToBuild.RCFiles).ObjectFiles);

            return LinkInputFiles;
        }
예제 #4
0
 /// <summary>
 /// Checks if any of the commands to execute has [RequireP4] attribute.
 /// </summary>
 /// <param name="CommandsToExecute">List of commands to be executed.</param>
 /// <param name="Commands">Commands.</param>
 /// <returns>True if any of the commands to execute has [RequireP4] attribute.</returns>
 private static bool CheckIfCommandsRequireP4(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
 {
     foreach (var CommandInfo in CommandsToExecute)
     {
         Type Command;
         if (Commands.TryGetValue(CommandInfo.CommandName, out Command))
         {
             var RequireP4Attributes = Command.GetCustomAttributes(typeof(RequireP4Attribute), true);
             if (!CommandUtils.IsNullOrEmpty(RequireP4Attributes))
             {
                 Log("Command {0} requires P4 functionality.", Command.Name);
                 return true;
             }
         }
     }
     return false;
 }
예제 #5
0
        /// <summary>
        /// Sets up P4Enabled, AllowSubmit properties. Note that this does not intialize P4 environment.
        /// </summary>
        /// <param name="CommandsToExecute">Commands to execute</param>
        /// <param name="Commands">Commands</param>
        internal static void InitP4Support(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
        {
            // Init AllowSubmit
            // If we do not specify on the commandline if submitting is allowed or not, this is
            // depending on whether we run locally or on a build machine.
            Log("Initializing AllowSubmit.");
            if (GlobalCommandLine.Submit || GlobalCommandLine.NoSubmit)
            {
                AllowSubmit = GlobalCommandLine.Submit;
            }
            else
            {
                AllowSubmit = Automation.IsBuildMachine;
            }
            Log("AllowSubmit={0}", AllowSubmit);

            // Init P4Enabled
            Log("Initializing P4Enabled.");
            if (Automation.IsBuildMachine)
            {
                P4Enabled = !GlobalCommandLine.NoP4;
            }
            else
            {
                P4Enabled = GlobalCommandLine.P4;
                if (!P4Enabled && !GlobalCommandLine.NoP4)
                {
                    // Check if any of the commands to execute require P4
                    P4Enabled = CheckIfCommandsRequireP4(CommandsToExecute, Commands);
                }
            }
            Log("P4Enabled={0}", P4Enabled);
        }
예제 #6
0
 /// <summary>
 /// Parses P4 forms and stores them as a key/value pairs.
 /// </summary>
 /// <param name="Output">P4 command output (must be a form).</param>
 /// <returns>Parsed output.</returns>
 public static CaselessDictionary<string> ParseTaggedP4Output(string Output)
 {
     var Tags = new CaselessDictionary<string>();
     var Lines = Output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
     string DelayKey = "";
     int DelayIndex = 0;
     foreach (var Line in Lines)
     {
         var TrimmedLine = Line.Trim();
         if (TrimmedLine.StartsWith("#") == false)
         {
             if (DelayKey != "")
             {
                 if (Line.StartsWith("\t"))
                 {
                     if (DelayIndex > 0)
                     {
                         Tags.Add(String.Format("{0}{1}", DelayKey, DelayIndex), TrimmedLine);
                     }
                     else
                     {
                         Tags.Add(DelayKey, TrimmedLine);
                     }
                     DelayIndex++;
                     continue;
                 }
                 DelayKey = "";
                 DelayIndex = 0;
             }
             var KeyEndIndex = TrimmedLine.IndexOf(':');
             if (KeyEndIndex >= 0)
             {
                 var Key = TrimmedLine.Substring(0, KeyEndIndex);
                 var Value = TrimmedLine.Substring(KeyEndIndex + 1).Trim();
                 if (Value == "")
                 {
                     DelayKey = Key;
                 }
                 else
                 {
                     Tags.Add(Key, Value);
                 }
             }
         }
     }
     return Tags;
 }
예제 #7
0
		/// <summary>
		/// Finds and/or compiles all script files and assemblies.
		/// </summary>
		/// <param name="ScriptsForProjectFileName">Path to the current project. May be null, in which case we compile scripts for all projects.</param>
		/// <param name="AdditionalScriptsFolders">Additional script fodlers to look for source files in.</param>
		public void FindAndCompileAllScripts(string ScriptsForProjectFileName, List<string> AdditionalScriptsFolders)
		{
			bool DoCompile = false;
			if (GlobalCommandLine.Compile)
			{
				DoCompile = true;
			}

			// Change to Engine\Source (if exists) to properly discover all UBT classes
			var OldCWD = Environment.CurrentDirectory;
			var UnrealBuildToolCWD = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source");
			if (Directory.Exists(UnrealBuildToolCWD))
			{
				Environment.CurrentDirectory = UnrealBuildToolCWD;
			}
			// Register all the classes inside UBT
			Log.TraceVerbose("Registering UBT Classes.");
			UnrealBuildTool.UnrealBuildTool.RegisterAllUBTClasses();
			Environment.CurrentDirectory = OldCWD;

			// Compile only if not disallowed.
			if (DoCompile && !String.IsNullOrEmpty(CommandUtils.CmdEnv.MsBuildExe))
			{
				CleanupScriptsAssemblies();
				FindAndCompileScriptModules(ScriptsForProjectFileName, AdditionalScriptsFolders);
			}

			var ScriptAssemblies = new List<Assembly>();
			LoadPreCompiledScriptAssemblies(ScriptAssemblies);

			// Setup platforms
			Platform.InitializePlatforms(ScriptAssemblies.ToArray());

			// Instantiate all the automation classes for interrogation
			Log.TraceVerbose("Creating commands.");
			ScriptCommands = new CaselessDictionary<Type>();
			foreach (var CompiledScripts in ScriptAssemblies)
			{
				foreach (var ClassType in CompiledScripts.GetTypes())
				{
					if (ClassType.IsSubclassOf(typeof(BuildCommand)) && ClassType.IsAbstract == false)
					{
						if (ScriptCommands.ContainsKey(ClassType.Name) == false)
						{
							ScriptCommands.Add(ClassType.Name, ClassType);
						}
						else
						{
							Log.TraceWarning("Unable to add command {0} twice. Previous: {1}, Current: {2}", ClassType.Name,
								ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName);
						}
					}
				}
			}
		}
예제 #8
0
		/// <summary>
		/// For any dependent module that has "SharedPCHHeaderFile" set in its module rules, we gather these headers
		/// and sort them in order from least-dependent to most-dependent such that larger, more complex PCH headers
		/// appear last in the list
		/// </summary>
		/// <returns>List of shared PCH headers to use</returns>
		private List<SharedPCHHeaderInfo> FindSharedPCHHeaders()
		{
			// List of modules, with all of the dependencies of that module
			var SharedPCHHeaderFiles = new List<SharedPCHHeaderInfo>();

			// Build up our list of modules with "shared PCH headers".  The list will be in dependency order, with modules
			// that depend on previous modules appearing later in the list
			foreach( var Binary in AppBinaries )
			{
				var CPPBinary = Binary as UEBuildBinaryCPP;
				if( CPPBinary != null )
				{
					foreach( var ModuleName in CPPBinary.ModuleNames )
					{
						var CPPModule = GetModuleByName( ModuleName ) as UEBuildModuleCPP;
						if( CPPModule != null )
						{
							if( !String.IsNullOrEmpty( CPPModule.SharedPCHHeaderFile ) && CPPModule.Binary.Config.bAllowCompilation )
							{
								// @todo SharedPCH: Ideally we could figure the PCH header name automatically, and simply use a boolean in the module
								//     definition to opt into exposing a shared PCH.  Unfortunately we don't determine which private PCH header "goes with"
								//     a module until a bit later in the process.  It shouldn't be hard to change that though.
								var SharedPCHHeaderFilePath = ProjectFileGenerator.RootRelativePath + "/Engine/Source/" + CPPModule.SharedPCHHeaderFile;
								var SharedPCHHeaderFileItem = FileItem.GetExistingItemByPath( SharedPCHHeaderFilePath );
								if( SharedPCHHeaderFileItem != null )
								{
									var ModuleDependencies = new CaselessDictionary<UEBuildModule.ModuleIndexPair>();
									bool bIncludeDynamicallyLoaded = false;
									CPPModule.GetAllDependencyModules(ModuleDependencies, bIncludeDynamicallyLoaded, bForceCircular: false, bOnlyDirectDependencies:false);

									// Figure out where to insert the shared PCH into our list, based off the module dependency ordering
									int InsertAtIndex = SharedPCHHeaderFiles.Count;
									for( var ExistingModuleIndex = SharedPCHHeaderFiles.Count - 1; ExistingModuleIndex >= 0; --ExistingModuleIndex )
									{
										var ExistingModule = SharedPCHHeaderFiles[ ExistingModuleIndex ].Module;
										var ExistingModuleDependencies = SharedPCHHeaderFiles[ ExistingModuleIndex ].Dependencies;

										// If the module to add to the list is dependent on any modules already in our header list, that module
										// must be inserted after any of those dependencies in the list
										foreach( var ExistingModuleDependency in ExistingModuleDependencies )
										{
											if( ExistingModuleDependency.Value == CPPModule )
											{
												// Make sure we're not a circular dependency of this module.  Circular dependencies always
												// point "upstream".  That is, modules like Engine point to UnrealEd in their
												// CircularlyReferencedDependentModules array, but the natural dependency order is
												// that UnrealEd depends on Engine.  We use this to avoid having modules such as UnrealEd
												// appear before Engine in our shared PCH list.
												// @todo SharedPCH: This is not very easy for people to discover.  Luckily we won't have many shared PCHs in total.
												if( !ExistingModule.CircularlyReferencedDependentModules.Contains( CPPModule.Name ) )
												{
													// We are at least dependent on this module.  We'll keep searching the list to find
													// further-descendant modules we might be dependent on
													InsertAtIndex = ExistingModuleIndex;
													break;
												}
											}
										}
									}

									var NewSharedPCHHeaderInfo = new SharedPCHHeaderInfo();
									NewSharedPCHHeaderInfo.PCHHeaderFile = SharedPCHHeaderFileItem;
									NewSharedPCHHeaderInfo.Module = CPPModule;
									NewSharedPCHHeaderInfo.Dependencies = ModuleDependencies.Values.OrderBy(x => x.Index).Select(x => x.Module).ToDictionary(M => M.Name);
									SharedPCHHeaderFiles.Insert( InsertAtIndex, NewSharedPCHHeaderInfo );
								}
								else
								{
									throw new BuildException( "Could not locate the specified SharedPCH header file '{0}' for module '{1}'.", SharedPCHHeaderFilePath, CPPModule.Name );
								}
							}
						}
					}
				}
			}

			if( SharedPCHHeaderFiles.Count > 0 )
			{
				Log.TraceVerbose("Detected {0} shared PCH headers (listed in dependency order):", SharedPCHHeaderFiles.Count);
				foreach( var CurSharedPCH in SharedPCHHeaderFiles )
				{
					Log.TraceVerbose("	" + CurSharedPCH.PCHHeaderFile.AbsolutePath + "  (module: " + CurSharedPCH.Module.Name + ")");
				}
			}
			else
			{
				Log.TraceVerbose("Did not detect any shared PCH headers");
			}
			return SharedPCHHeaderFiles;
		}
예제 #9
0
파일: P4Utils.cs 프로젝트: ErwinT6/T6Engine
		/// <summary>
		/// Checks if any of the commands to execute has [RequireP4] attribute.
		/// </summary>
		/// <param name="CommandsToExecute">List of commands to be executed.</param>
		/// <param name="Commands">Commands.</param>
		private static void CheckIfCommandsRequireP4(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands, out bool bRequireP4, out bool bRequireCL)
		{
			bRequireP4 = false;
			bRequireCL = false;

			foreach (var CommandInfo in CommandsToExecute)
			{
				Type Command;
				if (Commands.TryGetValue(CommandInfo.CommandName, out Command))
				{
					var RequireP4Attributes = Command.GetCustomAttributes(typeof(RequireP4Attribute), true);	
					if (!CommandUtils.IsNullOrEmpty(RequireP4Attributes))
					{
						LogWarning("Command {0} requires P4 functionality.", Command.Name);
						bRequireP4 = true;

						var DoesNotNeedP4CLAttributes = Command.GetCustomAttributes(typeof(DoesNotNeedP4CLAttribute), true);
						if (CommandUtils.IsNullOrEmpty(DoesNotNeedP4CLAttributes))
						{
							bRequireCL = true;
						}
					}
				}
			}
		}
예제 #10
0
파일: P4Utils.cs 프로젝트: ErwinT6/T6Engine
		/// <summary>
		/// Sets up P4Enabled, AllowSubmit properties. Note that this does not intialize P4 environment.
		/// </summary>
		/// <param name="CommandsToExecute">Commands to execute</param>
		/// <param name="Commands">Commands</param>
		internal static void InitP4Support(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
		{
			// Init AllowSubmit
			// If we do not specify on the commandline if submitting is allowed or not, this is 
			// depending on whether we run locally or on a build machine.
			LogVerbose("Initializing AllowSubmit.");
			if (GlobalCommandLine.Submit || GlobalCommandLine.NoSubmit)
			{
				AllowSubmit = GlobalCommandLine.Submit;
			}
			else
			{
				AllowSubmit = Automation.IsBuildMachine;
			}
			LogVerbose("AllowSubmit={0}", AllowSubmit);

			// Init P4Enabled
			LogVerbose("Initializing P4Enabled.");
			if (Automation.IsBuildMachine)
			{
				P4Enabled = !GlobalCommandLine.NoP4;
				P4CLRequired = P4Enabled;
			}
			else
			{
				bool bRequireP4;
				bool bRequireCL;
				CheckIfCommandsRequireP4(CommandsToExecute, Commands, out bRequireP4, out bRequireCL);

				P4Enabled = GlobalCommandLine.P4 || bRequireP4;
				P4CLRequired = GlobalCommandLine.P4 || bRequireCL;
			}
			LogVerbose("P4Enabled={0}", P4Enabled);
			LogVerbose("P4CLRequired={0}", P4CLRequired);
		}
예제 #11
0
		/// <summary>
		/// List all available commands.
		/// </summary>
		/// <param name="Commands">All vailable commands.</param>
		private static void ListAvailableCommands(CaselessDictionary<Type> Commands)
		{
			string Message = Environment.NewLine;
			Message += "Available commands:" + Environment.NewLine;
			foreach (var AvailableCommand in Commands)
			{
				Message += String.Format("  {0}{1}", AvailableCommand.Key, Environment.NewLine);
			}
			CommandUtils.Log(Message);
		}
예제 #12
0
		/// <summary>
		/// Display help for the specified commands (to execute)
		/// </summary>
		/// <param name="CommandsToExecute">List of commands specified in the command line.</param>
		/// <param name="Commands">All discovered command objects.</param>
		private static void DisplayHelp(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
		{
			for (int CommandIndex = 0; CommandIndex < CommandsToExecute.Count; ++CommandIndex)
			{
				var CommandInfo = CommandsToExecute[CommandIndex];
				Type CommandType;
				if (Commands.TryGetValue(CommandInfo.CommandName, out CommandType) == false)
				{
					Log.TraceError("Help: Failed to find command {0}", CommandInfo.CommandName);
				}
				else
				{
					CommandUtils.Help(CommandType);
				}
			}
		}
예제 #13
0
		/// <summary>
		/// Execute commands specified in the command line.
		/// </summary>
		/// <param name="CommandsToExecute"></param>
		/// <param name="Commands"></param>
		private static ExitCode Execute(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
		{
			for (int CommandIndex = 0; CommandIndex < CommandsToExecute.Count; ++CommandIndex)
			{
				var CommandInfo = CommandsToExecute[CommandIndex];
				Log.TraceVerbose("Attempting to execute {0}", CommandInfo.ToString());
				Type CommandType;
				if (!Commands.TryGetValue(CommandInfo.CommandName, out CommandType))
				{
					throw new AutomationException("Failed to find command {0}", CommandInfo.CommandName);
				}

				BuildCommand Command = (BuildCommand)Activator.CreateInstance(CommandType);
				Command.Params = CommandInfo.Arguments.ToArray();
				try
				{
					ExitCode Result = Command.Execute();
					if(Result != ExitCode.Success)
					{
						return Result;
					}
					CommandUtils.Log("BUILD SUCCESSFUL");
				}
				finally
				{
					// dispose of the class if necessary
					var CommandDisposable = Command as IDisposable;
					if (CommandDisposable != null)
					{
						CommandDisposable.Dispose();
					}
				}

				// Make sure there's no directories on the stack.
				CommandUtils.ClearDirStack();
			}
			return ExitCode.Success;
		}
예제 #14
0
		/// <summary>
		/// Execute commands specified in the command line.
		/// </summary>
		/// <param name="CommandsToExecute"></param>
		/// <param name="Commands"></param>
		private static void Execute(List<CommandInfo> CommandsToExecute, CaselessDictionary<Type> Commands)
		{
			for (int CommandIndex = 0; CommandIndex < CommandsToExecute.Count; ++CommandIndex)
			{
				var CommandInfo = CommandsToExecute[CommandIndex];
				Log.TraceVerbose("Attempting to execute {0}", CommandInfo.ToString());
				Type CommandType;
				if (!Commands.TryGetValue(CommandInfo.CommandName, out CommandType))
				{
					throw new AutomationException("Failed to find command {0}", CommandInfo.CommandName);
				}
				else
				{
					BuildCommand Command = (BuildCommand)Activator.CreateInstance(CommandType);
					Command.Params = CommandInfo.Arguments.ToArray();
					Command.Execute();
					// dispose of the class if necessary
					{
						var CommandDisposable = Command as IDisposable;
						if (CommandDisposable != null)
						{
							CommandDisposable.Dispose();
						}
					}

					// Make sure there's no directories on the stack.
					CommandUtils.ClearDirStack();
				}
			}

			Log.TraceInformation("Script execution successful, exiting.");
		}
예제 #15
0
        public override void GetAllDependencyModules( CaselessDictionary<ModuleIndexPair> ReferencedModules, bool bIncludeDynamicallyLoaded, bool bForceCircular, bool bOnlyDirectDependencies )
        {
            var AllModuleNames = new List<string>();
            AllModuleNames.AddRange(PrivateDependencyModuleNames);
            AllModuleNames.AddRange(PublicDependencyModuleNames);
            if( bIncludeDynamicallyLoaded )
            {
                AllModuleNames.AddRange(DynamicallyLoadedModuleNames);
                AllModuleNames.AddRange(PlatformSpecificDynamicallyLoadedModuleNames);
            }

            foreach (var DependencyName in AllModuleNames)
            {
                if (!ReferencedModules.ContainsKey(DependencyName))
                {
                    // Don't follow circular back-references!
                    bool bIsCircular = CircularlyReferencedDependentModules.Contains( DependencyName );
                    if (bForceCircular || !bIsCircular)
                    {
                        var Module = Target.GetModuleByName( DependencyName );
                        ReferencedModules[ DependencyName ] = null;

                        if( !bOnlyDirectDependencies )
                        {
                            // Recurse into dependent modules first
                            Module.GetAllDependencyModules(ReferencedModules, bIncludeDynamicallyLoaded, bForceCircular, bOnlyDirectDependencies);
                        }

                        ReferencedModules[ DependencyName ] = new ModuleIndexPair{ Module = Module, Index = ReferencedModules.Where(x => x.Value != null).Count() - 1 };
                    }
                }
            }
        }
예제 #16
0
 /**
  * Gets all of the modules referenced by this module
  *
  * @param	ReferencedModules	Hash of all referenced modules with their addition index.
  * @param	bIncludeDynamicallyLoaded	True if dynamically loaded modules (and all of their dependent modules) should be included.
  * @param	bForceCircular	True if circular dependencies should be processed
  * @param	bOnlyDirectDependencies	True to return only this module's direct dependencies
  */
 public virtual void GetAllDependencyModules(CaselessDictionary<ModuleIndexPair> ReferencedModules, bool bIncludeDynamicallyLoaded, bool bForceCircular, bool bOnlyDirectDependencies)
 {
 }
예제 #17
0
        /// <summary>
        /// Generates a list of all modules referenced by this binary
        /// </summary>
        /// <param name="bIncludeDynamicallyLoaded">True if dynamically loaded modules (and all of their dependent modules) should be included.</param>
        /// <param name="bForceCircular">True if circular dependencies should be process</param>
        /// <returns>List of all referenced modules</returns>
        public override List<UEBuildModule> GetAllDependencyModules(bool bIncludeDynamicallyLoaded, bool bForceCircular)
        {
            var ReferencedModules = new CaselessDictionary<UEBuildModule.ModuleIndexPair>();
            foreach( var ModuleName in ModuleNames )
            {
                if( !ReferencedModules.ContainsKey( ModuleName ) )
                {
                    var Module = Target.GetModuleByName( ModuleName );
                    ReferencedModules[ ModuleName ] = null;

                    Module.GetAllDependencyModules(ReferencedModules, bIncludeDynamicallyLoaded, bForceCircular, bOnlyDirectDependencies: false);

                    ReferencedModules[ ModuleName ] = new UEBuildModule.ModuleIndexPair{ Module = Module, Index = ReferencedModules.Count };
                }
            }

            return ReferencedModules.Values.OrderBy(M => M.Index).Select(M => M.Module).ToList();
        }
예제 #18
0
        /// <summary>
        /// Overrides base class to add module runtime dependencies to the build receipt.
        /// </summary>
        /// <param name="ToolChain">The platform toolchain</param>
        public override BuildReceipt MakeReceipt(IUEToolChain ToolChain)
        {
            BuildReceipt Receipt = base.MakeReceipt(ToolChain);

            // Set the IsPrecompiled flag on all the build products if we're not actually building this binary
            if(!Config.bAllowCompilation)
            {
                foreach(BuildProduct BuildProduct in Receipt.BuildProducts)
                {
                    BuildProduct.IsPrecompiled = true;
                }
            }

            // Add the compiled resource file if we're building a static library containing the launch module on Windows
            if(Config.Type == UEBuildBinaryType.StaticLibrary && ModuleNames.Contains("Launch") && (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64))
            {
                string ResourceFilePath = Path.Combine(Config.IntermediateDirectory, "Launch", "PCLaunch.rc.res");
                Receipt.AddBuildProduct(ResourceFilePath, BuildProductType.StaticLibrary);
            }

            // Add runtime dependencies for all the modules in this binary, and build up a list of all the referenced modules
            var ReferencedModules = new CaselessDictionary<UEBuildModule.ModuleIndexPair>();
            foreach (string ModuleName in ModuleNames)
            {
                UEBuildModule Module = Target.GetModuleByName(ModuleName);
                foreach(RuntimeDependency RuntimeDependency in Module.RuntimeDependencies)
                {
                    Receipt.RuntimeDependencies.Add(new RuntimeDependency(RuntimeDependency));
                }
                Module.GetAllDependencyModules(ReferencedModules, true, false, true);
            }

            // Add runtime dependencies for all the referenced external modules. These may be introduce dependencies for the binary without actually being listed for inclusion in it.
            foreach(UEBuildExternalModule ExternalModule in ReferencedModules.Values.OrderBy(x => x.Index).Select(x => x.Module).OfType<UEBuildExternalModule>())
            {
                foreach(RuntimeDependency RuntimeDependency in ExternalModule.RuntimeDependencies)
                {
                    Receipt.RuntimeDependencies.Add(new RuntimeDependency(RuntimeDependency));
                }
            }
            return Receipt;
        }
예제 #19
0
		void IDeserializationCallback.OnDeserialization(object sender)
		{
			if (OnlyModules == null)
			{
				OnlyModules = new List<OnlyModule>();
			}

			if (FlatModuleCsData == null)
			{
				FlatModuleCsData = new CaselessDictionary<FlatModuleCsDataType>();
			}
		}