Example #1
0
        /// <summary>
        /// Initialize the config system with the given types
        /// </summary>
        public static bool ReadConfigFiles()
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

            // Find all the input files
            FileReference[] InputFiles = FindInputFiles().Select(x => x.Location).ToArray();

            // Get the path to the cache file
            FileReference CacheFile  = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "XmlConfigCache.bin");
            FileReference SchemaFile = GetSchemaLocation();

            // Try to read the existing cache from disk
            XmlConfigData CachedValues;

            if (IsCacheUpToDate(CacheFile, InputFiles) && FileReference.Exists(SchemaFile))
            {
                if (XmlConfigData.TryRead(CacheFile, ConfigTypes, out CachedValues) && Enumerable.SequenceEqual(InputFiles, CachedValues.InputFiles))
                {
                    Values = CachedValues;
                }
            }

            // If that failed, regenerate it
            if (Values == null)
            {
                // Find all the configurable fields from the given types
                Dictionary <string, Dictionary <string, FieldInfo> > CategoryToFields = new Dictionary <string, Dictionary <string, FieldInfo> >();
                FindConfigurableFields(ConfigTypes, CategoryToFields);

                // Create a schema for the config files
                XmlSchema Schema = CreateSchema(CategoryToFields);
                WriteSchema(Schema, SchemaFile);

                // Read all the XML files and validate them against the schema
                Dictionary <Type, Dictionary <FieldInfo, object> > TypeToValues = new Dictionary <Type, Dictionary <FieldInfo, object> >();
                foreach (FileReference InputFile in InputFiles)
                {
                    if (!TryReadFile(InputFile, CategoryToFields, TypeToValues, Schema))
                    {
                        return(false);
                    }
                }

                // Create the new cache
                Values = new XmlConfigData(InputFiles, TypeToValues.ToDictionary(x => x.Key, x => x.Value.ToArray()));
                Values.Write(CacheFile);
            }

            // Apply all the static field values
            foreach (KeyValuePair <Type, KeyValuePair <FieldInfo, object>[]> TypeValuesPair in Values.TypeToValues)
            {
                foreach (KeyValuePair <FieldInfo, object> FieldValuePair in TypeValuesPair.Value)
                {
                    if (FieldValuePair.Key.IsStatic)
                    {
                        object Value = InstanceValue(FieldValuePair.Value, FieldValuePair.Key.FieldType);
                        FieldValuePair.Key.SetValue(null, Value);
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Gets the path to the tool binaries.
        /// </summary>
        /// <param name="Compiler">The compiler version</param>
        /// <param name="VCToolChainDir">Base directory for the VC toolchain</param>
        /// <param name="Architecture">Target Architecture</param>
        /// <returns>Directory containing the 32-bit toolchain binaries</returns>
        static DirectoryReference GetVCToolPath(WindowsCompiler Compiler, DirectoryReference VCToolChainDir, WindowsArchitecture Architecture)
        {
            if (Compiler >= WindowsCompiler.VisualStudio2017)
            {
                FileReference NativeCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "HostX64", WindowsExports.GetArchitectureSubpath(Architecture), "cl.exe");
                if (FileReference.Exists(NativeCompilerPath))
                {
                    return(NativeCompilerPath.Directory);
                }

                FileReference CrossCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "HostX86", WindowsExports.GetArchitectureSubpath(Architecture), "cl.exe");
                if (FileReference.Exists(CrossCompilerPath))
                {
                    return(CrossCompilerPath.Directory);
                }
            }
            else
            {
                if (Architecture == WindowsArchitecture.x86)
                {
                    FileReference CompilerPath = FileReference.Combine(VCToolChainDir, "bin", "cl.exe");
                    if (FileReference.Exists(CompilerPath))
                    {
                        return(CompilerPath.Directory);
                    }
                }
                else if (Architecture == WindowsArchitecture.x64)
                {
                    // Use the native 64-bit compiler if present
                    FileReference NativeCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "amd64", "cl.exe");
                    if (FileReference.Exists(NativeCompilerPath))
                    {
                        return(NativeCompilerPath.Directory);
                    }

                    // Otherwise use the amd64-on-x86 compiler. VS2012 Express only includes the latter.
                    FileReference CrossCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "x86_amd64", "cl.exe");
                    if (FileReference.Exists(CrossCompilerPath))
                    {
                        return(CrossCompilerPath.Directory);
                    }
                }
                else if (Architecture == WindowsArchitecture.ARM32)
                {
                    // Use the native 64-bit compiler if present
                    FileReference NativeCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "amd64_arm", "cl.exe");
                    if (FileReference.Exists(NativeCompilerPath))
                    {
                        return(NativeCompilerPath.Directory);
                    }

                    // Otherwise use the amd64-on-x86 compiler. VS2012 Express only includes the latter.
                    FileReference CrossCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "x86_arm", "cl.exe");
                    if (FileReference.Exists(CrossCompilerPath))
                    {
                        return(CrossCompilerPath.Directory);
                    }
                }
            }

            throw new BuildException("No required compiler toolchain found in {0}", VCToolChainDir);
        }
        /// <summary>
        /// Creates a rules assembly
        /// </summary>
        /// <param name="Scope">Scope for items created from this assembly</param>
        /// <param name="RootDirectories">The root directories to create rules for</param>
        /// <param name="AssemblyPrefix">A prefix for the assembly file name</param>
        /// <param name="Plugins">List of plugins to include in this assembly</param>
        /// <param name="bReadOnly">Whether the assembly should be marked as installed</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        /// <returns>New rules assembly</returns>
        private static RulesAssembly CreateEngineOrEnterpriseRulesAssembly(RulesScope Scope, List <DirectoryReference> RootDirectories, string AssemblyPrefix, IReadOnlyList <PluginInfo> Plugins, bool bReadOnly, bool bSkipCompile, RulesAssembly Parent)
        {
            // Scope hierarchy
            RulesScope PluginsScope  = new RulesScope(Scope.Name + " Plugins", Scope);
            RulesScope ProgramsScope = new RulesScope(Scope.Name + " Programs", PluginsScope);

            // Find the shared modules, excluding the programs directory. These are used to create an assembly with the bContainsEngineModules flag set to true.
            Dictionary <FileReference, ModuleRulesContext> ModuleFileToContext = new Dictionary <FileReference, ModuleRulesContext>();
            ModuleRulesContext DefaultModuleContext = new ModuleRulesContext(Scope, RootDirectories[0]);

            foreach (DirectoryReference RootDirectory in RootDirectories)
            {
                using (Timeline.ScopeEvent("Finding engine modules"))
                {
                    DirectoryReference SourceDirectory = DirectoryReference.Combine(RootDirectory, "Source");

                    AddEngineModuleRulesWithContext(SourceDirectory, "Runtime", DefaultModuleContext, UHTModuleType.EngineRuntime, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "Developer", DefaultModuleContext, UHTModuleType.EngineDeveloper, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "Editor", DefaultModuleContext, UHTModuleType.EngineEditor, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "ThirdParty", DefaultModuleContext, UHTModuleType.EngineThirdParty, ModuleFileToContext);
                }
            }

            // Add all the plugin modules too (don't need to loop over RootDirectories since the plugins come in already found
            using (Timeline.ScopeEvent("Finding plugin modules"))
            {
                ModuleRulesContext PluginsModuleContext = new ModuleRulesContext(PluginsScope, RootDirectories[0]);
                FindModuleRulesForPlugins(Plugins, PluginsModuleContext, ModuleFileToContext);
            }

            // Create the assembly
            DirectoryReference AssemblyDir            = RootDirectories[0];
            FileReference      EngineAssemblyFileName = FileReference.Combine(AssemblyDir, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "Rules" + FrameworkAssemblyExtension);
            RulesAssembly      EngineAssembly         = new RulesAssembly(Scope, RootDirectories, Plugins, ModuleFileToContext, new List <FileReference>(), EngineAssemblyFileName, bContainsEngineModules: true, DefaultBuildSettings: BuildSettingsVersion.Latest, bReadOnly: bReadOnly, bSkipCompile: bSkipCompile, Parent: Parent);

            List <FileReference> ProgramTargetFiles = new List <FileReference>();
            Dictionary <FileReference, ModuleRulesContext> ProgramModuleFiles = new Dictionary <FileReference, ModuleRulesContext>();

            foreach (DirectoryReference RootDirectory in RootDirectories)
            {
                DirectoryReference SourceDirectory   = DirectoryReference.Combine(RootDirectory, "Source");
                DirectoryReference ProgramsDirectory = DirectoryReference.Combine(SourceDirectory, "Programs");

                // Also create a scope for them, and update the UHT module type
                ModuleRulesContext ProgramsModuleContext = new ModuleRulesContext(ProgramsScope, RootDirectory);
                ProgramsModuleContext.DefaultUHTModuleType = UHTModuleType.Program;

                using (Timeline.ScopeEvent("Finding program modules"))
                {
                    // Find all the rules files
                    AddModuleRulesWithContext(ProgramsDirectory, ProgramsModuleContext, ProgramModuleFiles);
                }

                using (Timeline.ScopeEvent("Finding program targets"))
                {
                    ProgramTargetFiles.AddRange(FindAllRulesFiles(SourceDirectory, RulesFileType.Target));
                }
            }

            // Create a path to the assembly that we'll either load or compile
            FileReference ProgramAssemblyFileName = FileReference.Combine(AssemblyDir, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "ProgramRules" + FrameworkAssemblyExtension);
            RulesAssembly ProgramAssembly         = new RulesAssembly(ProgramsScope, RootDirectories, new List <PluginInfo>().AsReadOnly(), ProgramModuleFiles, ProgramTargetFiles, ProgramAssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: BuildSettingsVersion.Latest, bReadOnly: bReadOnly, bSkipCompile: bSkipCompile, Parent: EngineAssembly);

            // Return the combined assembly
            return(ProgramAssembly);
        }
Example #4
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="ProjectFile">Project to read settings from</param>
        public RemoteMac(FileReference ProjectFile)
        {
            this.RsyncExe         = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Rsync.exe");
            this.SshExe           = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "ThirdPartyNotUE", "DeltaCopy", "Binaries", "Ssh.exe");
            this.ProjectFile      = ProjectFile;
            this.ProjectDirectory = DirectoryReference.FromFile(ProjectFile);

            // Apply settings from the XML file
            XmlConfig.ApplyTo(this);

            // Get the project config file path
            DirectoryReference EngineIniPath = ProjectFile != null ? ProjectFile.Directory : null;

            if (EngineIniPath == null && UnrealBuildTool.GetRemoteIniPath() != null)
            {
                EngineIniPath = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath());
            }
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, EngineIniPath, UnrealTargetPlatform.IOS);

            // Read the project settings if we don't have anything in the build configuration settings
            if (String.IsNullOrEmpty(ServerName))
            {
                // Read the server name
                string IniServerName;
                if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RemoteServerName", out IniServerName) && !String.IsNullOrEmpty(IniServerName))
                {
                    this.ServerName = IniServerName;
                }
                else
                {
                    throw new BuildException("Remote compiling requires a server name. Use the editor (Project Settings > IOS) to set up your remote compilation settings.");
                }

                // Parse the username
                string IniUserName;
                if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "RSyncUsername", out IniUserName) && !String.IsNullOrEmpty(IniUserName))
                {
                    this.UserName = IniUserName;
                }
            }

            // Split port out from the server name
            int PortIdx = ServerName.LastIndexOf(':');

            if (PortIdx != -1)
            {
                string Port = ServerName.Substring(PortIdx + 1);
                if (!int.TryParse(Port, out ServerPort))
                {
                    throw new BuildException("Unable to parse port number from '{0}'", ServerName);
                }
                ServerName = ServerName.Substring(0, PortIdx);
            }

            // If a user name is not set, use the current user
            if (String.IsNullOrEmpty(UserName))
            {
                UserName = Environment.UserName;
            }

            // Print out the server info
            Log.TraceInformation("[Remote] Using remote server '{0}' on port {1} (user '{2}')", ServerName, ServerPort, UserName);

            // Get the path to the SSH private key
            string OverrideSshPrivateKeyPath;

            if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SSHPrivateKeyOverridePath", out OverrideSshPrivateKeyPath) && !String.IsNullOrEmpty(OverrideSshPrivateKeyPath))
            {
                SshPrivateKey = new FileReference(OverrideSshPrivateKeyPath);
                if (!FileReference.Exists(SshPrivateKey))
                {
                    throw new BuildException("SSH private key specified in config file ({0}) does not exist.", SshPrivateKey);
                }
            }

            // If it's not set, look in the standard locations. If that fails, spawn the batch file to generate one.
            if (SshPrivateKey == null && !TryGetSshPrivateKey(out SshPrivateKey))
            {
                Log.TraceWarning("No SSH private key found for {0}@{1}. Launching SSH to generate one.", UserName, ServerName);

                StringBuilder CommandLine = new StringBuilder();
                CommandLine.AppendFormat("/C \"\"{0}\"", FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "BatchFiles", "MakeAndInstallSSHKey.bat"));
                CommandLine.AppendFormat(" \"{0}\"", SshExe);
                CommandLine.AppendFormat(" \"{0}\"", ServerPort);
                CommandLine.AppendFormat(" \"{0}\"", RsyncExe);
                CommandLine.AppendFormat(" \"{0}\"", UserName);
                CommandLine.AppendFormat(" \"{0}\"", ServerName);
                CommandLine.AppendFormat(" \"{0}\"", DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments));
                CommandLine.AppendFormat(" \"{0}\"", GetLocalCygwinPath(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.MyDocuments)));
                CommandLine.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineDirectory);
                CommandLine.Append("\"");

                using (Process ChildProcess = Process.Start("C:\\Windows\\System32\\Cmd.exe", CommandLine.ToString()))
                {
                    ChildProcess.WaitForExit();
                }

                if (!TryGetSshPrivateKey(out SshPrivateKey))
                {
                    throw new BuildException("Failed to generate SSH private key for {0}@{1}.", UserName, ServerName);
                }
            }

            // resolve the rest of the strings
            RsyncAuthentication = ExpandVariables(RsyncAuthentication);
            SshAuthentication   = ExpandVariables(SshAuthentication);

            // Build a list of arguments for SSH
            CommonSshArguments = new List <string>();
            CommonSshArguments.Add("-o BatchMode=yes");
            CommonSshArguments.Add(SshAuthentication);
            CommonSshArguments.Add(String.Format("-p {0}", ServerPort));
            CommonSshArguments.Add(String.Format("\"{0}@{1}\"", UserName, ServerName));

            // Build a list of arguments for Rsync
            BasicRsyncArguments = new List <string>();
            BasicRsyncArguments.Add("--compress");
            BasicRsyncArguments.Add("--verbose");
            BasicRsyncArguments.Add(String.Format("--rsh=\"{0} -p {1}\"", RsyncAuthentication, ServerPort));
            BasicRsyncArguments.Add("--chmod=ugo=rwx");

            // Build a list of arguments for Rsync filters
            CommonRsyncArguments = new List <string>(BasicRsyncArguments);
            CommonRsyncArguments.Add("--recursive");
            CommonRsyncArguments.Add("--delete");            // Delete anything not in the source directory
            CommonRsyncArguments.Add("--delete-excluded");   // Delete anything not in the source directory
            CommonRsyncArguments.Add("--times");             // Preserve modification times
            CommonRsyncArguments.Add("--prune-empty-dirs");  // Remove empty directories from the file list

            // Get the remote base directory
            StringBuilder Output;

            if (ExecuteAndCaptureOutput("'echo ~'", out Output) != 0)
            {
                throw new BuildException("Unable to determine home directory for remote user");
            }
            RemoteBaseDir = String.Format("{0}/UE4/Builds/{1}", Output.ToString().Trim().TrimEnd('/'), Environment.MachineName);
            Log.TraceInformation("[Remote] Using base directory '{0}'", RemoteBaseDir);

            // Build the list of directory mappings between the local and remote machines
            Mappings = new List <RemoteMapping>();
            Mappings.Add(new RemoteMapping(UnrealBuildTool.EngineDirectory, GetRemotePath(UnrealBuildTool.EngineDirectory)));
            if (ProjectFile != null && !ProjectFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
            {
                Mappings.Add(new RemoteMapping(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory)));
            }
        }
Example #5
0
        /// <summary>
        /// Upload all the files in the workspace for the current project
        /// </summary>
        void UploadWorkspace(DirectoryReference TempDir)
        {
            // Path to the scripts to be uploaded
            FileReference ScriptPathsFileName = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngineScripts.txt");

            // Read the list of scripts to be uploaded
            List <string> ScriptPaths = new List <string>();

            foreach (string Line in FileReference.ReadAllLines(ScriptPathsFileName))
            {
                string FileToUpload = Line.Trim();
                if (FileToUpload.Length > 0 && FileToUpload[0] != '#')
                {
                    ScriptPaths.Add(FileToUpload);
                }
            }

            // Fixup the line endings
            List <FileReference> TargetFiles = new List <FileReference>();

            foreach (string ScriptPath in ScriptPaths)
            {
                FileReference SourceFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, ScriptPath.TrimStart('/'));
                if (!FileReference.Exists(SourceFile))
                {
                    throw new BuildException("Missing script required for remote upload: {0}", SourceFile);
                }

                FileReference TargetFile = FileReference.Combine(TempDir, SourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory));
                if (!FileReference.Exists(TargetFile) || FileReference.GetLastWriteTimeUtc(TargetFile) < FileReference.GetLastWriteTimeUtc(SourceFile))
                {
                    DirectoryReference.CreateDirectory(TargetFile.Directory);
                    string ScriptText = FileReference.ReadAllText(SourceFile);
                    FileReference.WriteAllText(TargetFile, ScriptText.Replace("\r\n", "\n"));
                }
                TargetFiles.Add(TargetFile);
            }

            // Write a file that protects all the scripts from being overridden by the standard engine filters
            FileReference ScriptProtectList = FileReference.Combine(TempDir, "RsyncEngineScripts-Protect.txt");

            using (StreamWriter Writer = new StreamWriter(ScriptProtectList.FullName))
            {
                foreach (string ScriptPath in ScriptPaths)
                {
                    Writer.WriteLine("protect {0}", ScriptPath);
                }
            }

            // Upload these files to the remote
            Log.TraceInformation("[Remote] Uploading scripts...");
            UploadFiles(TempDir, GetRemotePath(UnrealBuildTool.EngineDirectory), ScriptPathsFileName);

            // Upload the config files
            Log.TraceInformation("[Remote] Uploading config files...");
            UploadFile(XmlConfig.CacheFile);

            // Upload the engine files
            List <FileReference> EngineFilters = new List <FileReference>();

            EngineFilters.Add(ScriptProtectList);
            if (UnrealBuildTool.IsEngineInstalled())
            {
                EngineFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngineInstalled.txt"));
            }
            EngineFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngine.txt"));

            Log.TraceInformation("[Remote] Uploading engine files...");
            UploadDirectory(UnrealBuildTool.EngineDirectory, GetRemotePath(UnrealBuildTool.EngineDirectory), EngineFilters);

            // Upload the project files
            if (ProjectFile != null && !ProjectFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
            {
                List <FileReference> ProjectFilters = new List <FileReference>();

                FileReference CustomProjectFilter = FileReference.Combine(ProjectFile.Directory, "Build", "Rsync", "RsyncProject.txt");
                if (FileReference.Exists(CustomProjectFilter))
                {
                    ProjectFilters.Add(CustomProjectFilter);
                }
                ProjectFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncProject.txt"));

                Log.TraceInformation("[Remote] Uploading project files...");
                UploadDirectory(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory), ProjectFilters);
            }
        }
Example #6
0
        public static FileReference GetUBTMakefilePath(FileReference ProjectFile, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, string TargetName, bool bForHotReload)
        {
            DirectoryReference BaseDir = GetUBTMakefileDirectory(ProjectFile, Platform, Configuration, TargetName);

            return(FileReference.Combine(BaseDir, bForHotReload ? "HotReloadMakefile.ubt" : "Makefile.ubt"));
        }
Example #7
0
        private LinkEnvironment SetupBinaryLinkEnvironment(UEBuildTarget Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ActionGraph ActionGraph)
        {
            LinkEnvironment         BinaryLinkEnvironment         = LinkEnvironment.DeepCopy();
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CompileEnvironment.Config.bIsBuildingDLL     = IsBuildingDll(Config.Type);
            CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

            CPPEnvironment BinaryCompileEnvironment = CompileEnvironment.DeepCopy();

            // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency.
            // We flag the compile environment when we build UHT so that we don't need to check
            // this for each file when generating their dependencies.
            BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool");

            // @todo: This should be in some Windows code somewhere...
            // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
            string OriginalFilename = (Config.OriginalOutputFilePaths != null) ?
                                      Config.OriginalOutputFilePaths[0].GetFileName() :
                                      Config.OutputFilePaths[0].GetFileName();

            BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SharedPCHs, ActionGraph);

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    // Allow the module to modify the link environment for the binary.
                    Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules);
                }
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
            if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
            {
                BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
            }

            // Set the link output file.
            BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.Config.OutputDirectory = Config.OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.Config.bIsBuildingDLL     = IsBuildingDll(Config.Type);
            BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

            BinaryLinkEnvironment.Config.ProjectFile = Target.ProjectFile;

            // Add the default resources for dlls
            if (Config.Type == UEBuildBinaryType.DynamicLinkLibrary)
            {
                // Check if there's already a custom resource file
                if (!BinaryLinkEnvironment.InputFiles.Any(x => x.Reference.HasExtension(".res")))
                {
                    if (UEBuildConfiguration.bFormalBuild)
                    {
                        // For formal builds, compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        CPPEnvironment BinaryResourceCompileEnvironment = BinaryCompileEnvironment.DeepCopy();
                        BinaryResourceCompileEnvironment.Config.OutputDirectory = DirectoryReference.Combine(BinaryResourceCompileEnvironment.Config.OutputDirectory, Modules.First().Name);
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(BinaryResourceCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ActionGraph);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                    else
                    {
                        // For non-formal builds, we just want to share the default resource file between modules
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                }

                // Add all the common resource files
                BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);
            }

            return(BinaryLinkEnvironment);
        }
Example #8
0
        /// <summary>
        /// Returns a list of INI filenames for the given project
        /// </summary>
        private static IEnumerable <FileReference> EnumerateCrossPlatformIniFileNames(DirectoryReference ProjectDirectory, DirectoryReference EngineDirectory, UnrealTargetPlatform Platform, string BaseIniName, bool SkipEngine)
        {
            string PlatformName = GetIniPlatformName(Platform);

            if (!SkipEngine)
            {
                // Engine/Config/Base.ini (included in every ini type, required)
                yield return(FileReference.Combine(EngineDirectory, "Config", "Base.ini"));

                // Engine/Config/Base* ini
                yield return(FileReference.Combine(EngineDirectory, "Config", "Base" + BaseIniName + ".ini"));

                if (Platform != UnrealTargetPlatform.Unknown)
                {
                    // Engine/Config/Platform/BasePlatform* ini
                    yield return(FileReference.Combine(EngineDirectory, "Config", PlatformName, "Base" + PlatformName + BaseIniName + ".ini"));
                }

                // Engine/Config/NotForLicensees/Base* ini
                yield return(FileReference.Combine(EngineDirectory, "Config", "NotForLicensees", "Base" + BaseIniName + ".ini"));

                // NOTE: 4.7: See comment in GetSourceIniHierarchyFilenames()
                // Engine/Config/NoRedist/Base* ini
                // yield return Path.Combine(EngineDirectory, "Config", "NoRedist", "Base" + BaseIniName + ".ini");
            }

            if (ProjectDirectory != null)
            {
                // Game/Config/Default* ini
                yield return(FileReference.Combine(ProjectDirectory, "Config", "Default" + BaseIniName + ".ini"));

                // Game/Config/NotForLicensees/Default* ini
                yield return(FileReference.Combine(ProjectDirectory, "Config", "NotForLicensees", "Default" + BaseIniName + ".ini"));

                // Game/Config/NoRedist/Default* ini
                yield return(FileReference.Combine(ProjectDirectory, "Config", "NoRedist", "Default" + BaseIniName + ".ini"));
            }

            if (Platform != UnrealTargetPlatform.Unknown)
            {
                // Engine/Config/Platform/Platform* ini
                yield return(FileReference.Combine(EngineDirectory, "Config", PlatformName, PlatformName + BaseIniName + ".ini"));

                if (ProjectDirectory != null)
                {
                    // Game/Config/Platform/Platform* ini
                    yield return(FileReference.Combine(ProjectDirectory, "Config", PlatformName, PlatformName + BaseIniName + ".ini"));
                }
            }

            DirectoryReference UserSettingsFolder = Utils.GetUserSettingDirectory();             // Match FPlatformProcess::UserSettingsDir()

            if (UserSettingsFolder != null)
            {
                // <AppData>/UE4/EngineConfig/User* ini
                yield return(FileReference.Combine(UserSettingsFolder, "Unreal Engine", "Engine", "Config", "User" + BaseIniName + ".ini"));
            }

            // Some user accounts (eg. SYSTEM on Windows) don't have a home directory. Ignore them if Environment.GetFolderPath() returns an empty string.
            string PersonalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

            if (!String.IsNullOrEmpty(PersonalFolder))
            {
                DirectoryReference PersonalConfigFolder;                 // Match FPlatformProcess::UserDir()
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    PersonalConfigFolder = new DirectoryReference(Path.Combine(PersonalFolder, "Documents"));
                }
                else if (Environment.OSVersion.Platform == PlatformID.Unix)
                {
                    PersonalConfigFolder = new DirectoryReference(Path.Combine(PersonalFolder, "Documents"));
                }
                else
                {
                    PersonalConfigFolder = new DirectoryReference(PersonalFolder);
                }

                // <Documents>/UE4/EngineConfig/User* ini
                yield return(FileReference.Combine(PersonalConfigFolder, "Unreal Engine", "Engine", "Config", "User" + BaseIniName + ".ini"));
            }

            // Game/Config/User* ini
            if (ProjectDirectory != null)
            {
                yield return(FileReference.Combine(ProjectDirectory, "Config", "User" + BaseIniName + ".ini"));
            }
        }
Example #9
0
 /// <summary>
 /// Get the name of the response file for the current linker environment and output file
 /// </summary>
 /// <param name="LinkEnvironment"></param>
 /// <param name="OutputFile"></param>
 /// <returns></returns>
 public static FileReference GetResponseFileName(LinkEnvironment LinkEnvironment, FileItem OutputFile)
 {
     // Construct a relative path for the intermediate response file
     return(FileReference.Combine(LinkEnvironment.IntermediateDirectory, OutputFile.Location.GetFileName() + ".response"));
 }
Example #10
0
        protected IOSProvisioningData(IOSProjectSettings ProjectSettings, bool bIsTVOS, bool bForDistribtion)
        {
            SigningCertificate = ProjectSettings.SigningCertificate;
            string MobileProvision = ProjectSettings.MobileProvision;

            FileReference ProjectFile = ProjectSettings.ProjectFile;

            if (!string.IsNullOrEmpty(SigningCertificate))
            {
                // verify the certificate
                Process IPPProcess = new Process();
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                else
                {
                    string IPPCmd = "certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                Utils.RunLocalProcess(IPPProcess);
            }
            else
            {
                SigningCertificate = bForDistribtion ? "iPhone Distribution" : "iPhone Developer";
                bHaveCertificate   = true;
            }

            if (!string.IsNullOrEmpty(MobileProvision))
            {
                DirectoryReference MobileProvisionDir;
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    MobileProvisionDir = DirectoryReference.Combine(new DirectoryReference(Environment.GetEnvironmentVariable("HOME")), "Library", "MobileDevice", "Provisioning Profiles");
                }
                else
                {
                    MobileProvisionDir = DirectoryReference.Combine(DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.LocalApplicationData), "Apple Computer", "MobileDevice", "Provisioning Profiles");
                }

                FileReference PossibleMobileProvisionFile = FileReference.Combine(MobileProvisionDir, MobileProvision);
                if (FileReference.Exists(PossibleMobileProvisionFile))
                {
                    MobileProvisionFile = PossibleMobileProvisionFile;
                }
            }

            if (MobileProvisionFile == null || !bHaveCertificate)
            {
                SigningCertificate  = "";
                MobileProvision     = "";
                MobileProvisionFile = null;
                Log.TraceLog("Provision not specified or not found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", searching for compatible match...");
                Process IPPProcess = new Process();
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                {
                    string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                else
                {
                    string IPPCmd = "signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + ProjectSettings.BundleIdentifier + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                    IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                    IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                    IPPProcess.StartInfo.Arguments        = IPPCmd;
                    IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                }
                Utils.RunLocalProcess(IPPProcess);
                if (MobileProvisionFile != null)
                {
                    Log.TraceLog("Provision found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", Provision: " + MobileProvisionFile + " Certificate: " + SigningCertificate);
                }
            }

            // add to the dictionary
            SigningCertificate = SigningCertificate.Replace("\"", "");

            // read the provision to get the UUID
            if (MobileProvisionFile == null)
            {
                Log.TraceLog("No matching provision file was discovered for {0}. Please ensure you have a compatible provision installed.", ProjectFile);
            }
            else if (!FileReference.Exists(MobileProvisionFile))
            {
                Log.TraceLog("Selected mobile provision for {0} ({1}) was not found. Please ensure you have a compatible provision installed.", ProjectFile, MobileProvisionFile);
            }
            else
            {
                byte[] AllBytes = FileReference.ReadAllBytes(MobileProvisionFile);

                uint StartIndex = (uint)AllBytes.Length;
                uint EndIndex   = (uint)AllBytes.Length;

                for (uint i = 0; i + 4 < AllBytes.Length; i++)
                {
                    if (AllBytes[i] == '<' && AllBytes[i + 1] == '?' && AllBytes[i + 2] == 'x' && AllBytes[i + 3] == 'm' && AllBytes[i + 4] == 'l')
                    {
                        StartIndex = i;
                        break;
                    }
                }

                if (StartIndex < AllBytes.Length)
                {
                    for (uint i = StartIndex; i + 7 < AllBytes.Length; i++)
                    {
                        if (AllBytes[i] == '<' && AllBytes[i + 1] == '/' && AllBytes[i + 2] == 'p' && AllBytes[i + 3] == 'l' && AllBytes[i + 4] == 'i' && AllBytes[i + 5] == 's' && AllBytes[i + 6] == 't' && AllBytes[i + 7] == '>')
                        {
                            EndIndex = i + 7;
                            break;
                        }
                    }
                }

                if (StartIndex < AllBytes.Length && EndIndex < AllBytes.Length)
                {
                    byte[] TextBytes = new byte[EndIndex - StartIndex];
                    Buffer.BlockCopy(AllBytes, (int)StartIndex, TextBytes, 0, (int)(EndIndex - StartIndex));

                    string AllText = Encoding.UTF8.GetString(TextBytes);
                    int    idx     = AllText.IndexOf("<key>UUID</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx += "<string>".Length;
                            MobileProvisionUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                    idx = AllText.IndexOf("<key>com.apple.developer.team-identifier</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx     += "<string>".Length;
                            TeamUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                    idx = AllText.IndexOf("<key>Name</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx += "<string>".Length;
                            MobileProvisionName = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                }

                if (string.IsNullOrEmpty(MobileProvisionUUID) || string.IsNullOrEmpty(TeamUUID))
                {
                    MobileProvision    = null;
                    SigningCertificate = null;
                    Log.TraceLog("Failed to parse the mobile provisioning profile.");
                }
            }
        }
Example #11
0
        private LinkEnvironment SetupBinaryLinkEnvironment(ReadOnlyTargetRules Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CppCompileEnvironment CompileEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ISourceFileWorkingSet WorkingSet, DirectoryReference ExeDir, ActionGraph ActionGraph)
        {
            LinkEnvironment         BinaryLinkEnvironment         = new LinkEnvironment(LinkEnvironment);
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CppCompileEnvironment BinaryCompileEnvironment = CreateBinaryCompileEnvironment(CompileEnvironment);

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SharedPCHs, WorkingSet, ActionGraph);

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                // Allow the module to modify the link environment for the binary.
                Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules, ExeDir);
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
            if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
            {
                BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
            }

            // Set the link output file.
            BinaryLinkEnvironment.OutputFilePaths = OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.bHasExports = bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.IntermediateDirectory = IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.OutputDirectory = OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.bIsBuildingDLL     = IsBuildingDll(Type);
            BinaryLinkEnvironment.bIsBuildingLibrary = IsBuildingLibrary(Type);

            // If we don't have any resource file, use the default or compile a custom one for this module
            if (BinaryLinkEnvironment.Platform == CppPlatform.Win32 || BinaryLinkEnvironment.Platform == CppPlatform.Win64)
            {
                if (!BinaryLinkEnvironment.InputFiles.Any(x => x.Location.HasExtension(".res")))
                {
                    if (BinaryLinkEnvironment.DefaultResourceFiles.Count > 0)
                    {
                        // Use the default resource file if possible
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                    else
                    {
                        // Get the intermediate directory
                        DirectoryReference ResourceIntermediateDirectory = ((UEBuildModuleCPP)Modules.First()).IntermediateDirectory;

                        // Create a compile environment for resource files
                        CppCompileEnvironment ResourceCompileEnvironment = new CppCompileEnvironment(BinaryCompileEnvironment);
                        WindowsPlatform.SetupResourceCompileEnvironment(ResourceCompileEnvironment, ResourceIntermediateDirectory, Target);

                        // @todo: This should be in some Windows code somewhere...
                        // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
                        string OriginalFilename = (OriginalOutputFilePaths != null) ? OriginalOutputFilePaths[0].GetFileName() : OutputFilePaths[0].GetFileName();
                        ResourceCompileEnvironment.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

                        // Set the other version fields
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILT_FROM_CHANGELIST={0}", Target.Version.Changelist));
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILD_VERSION={0}", Target.BuildVersion));

                        // Otherwise compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(ResourceCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ResourceIntermediateDirectory, ActionGraph);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                }
            }

            // Add all the common resource files
            BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);

            return(BinaryLinkEnvironment);
        }
Example #12
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            if (CompileEnvironment.Config.Target.Architecture == "-win32")             // simulator
            {
                return(base.CompileCPPFiles(Target, CompileEnvironment, SourceFiles, ModuleName));
            }

            string Arguments = GetCLArguments_Global(CompileEnvironment);

            CPPOutput Result = new CPPOutput();

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }


            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D{0}", Definition);
            }

            if (bEnableTracing)
            {
                Arguments += string.Format(" -D__EMSCRIPTEN_TRACING__");
            }

            var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                bool   bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                // Add the C++ source file and its included files to the prerequisite item list.
                AddPrerequisiteSourceFile(Target, BuildPlatform, CompileEnvironment, SourceFile, CompileAction.PrerequisiteItems);

                // Add the source file path to the command-line.
                string FileArguments       = string.Format(" \"{0}\"", SourceFile.AbsolutePath);
                var    ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.HTML5).GetBinaryExtension(UEBuildBinaryType.Object);
                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath);

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    FileArguments += GetCLArguments_C(CompileEnvironment.Config.Target.Architecture);
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
                CompileAction.CommandPath      = HTML5SDKInfo.Python();

                CompileAction.CommandArguments = HTML5SDKInfo.EmscriptenCompiler() + " " + Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;

                //System.Console.WriteLine(CompileAction.CommandArguments);
                CompileAction.StatusDescription  = Path.GetFileName(SourceFile.AbsolutePath);
                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

                // Don't farm out creation of precomputed headers as it is the critical path task.
                CompileAction.bCanExecuteRemotely = CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create;

                // this is the final output of the compile step (a .abc file)
                Result.ObjectFiles.Add(ObjectFile);

                // VC++ always outputs the source file name being compiled, so we don't need to emit this ourselves
                CompileAction.bShouldOutputStatusDescription = true;

                // Don't farm out creation of precompiled headers as it is the critical path task.
                CompileAction.bCanExecuteRemotely =
                    CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create ||
                    BuildConfiguration.bAllowRemotelyCompiledPCHs;
            }

            return(Result);
        }
Example #13
0
        /// <summary>
        /// Dynamically compiles an assembly for the specified source file and loads that assembly into the application's
        /// current domain.  If an assembly has already been compiled and is not out of date, then it will be loaded and
        /// no compilation is necessary.
        /// </summary>
        /// <param name="SourceFileNames">List of source file name</param>
        /// <param name="OutputAssemblyPath">Full path to the assembly to be created</param>
        /// <returns>The assembly that was loaded</returns>
        public static Assembly CompileAndLoadAssembly(FileReference OutputAssemblyPath, List <FileReference> SourceFileNames, List <string> ReferencedAssembies = null, List <string> PreprocessorDefines = null, bool DoNotCompile = false, bool TreatWarningsAsErrors = false)
        {
            // Check to see if the resulting assembly is compiled and up to date
            FileReference AssemblySourcesListFilePath = FileReference.Combine(OutputAssemblyPath.Directory, Path.GetFileNameWithoutExtension(OutputAssemblyPath.FullName) + "SourceFiles.txt");
            bool          bNeedsCompilation           = false;

            if (!DoNotCompile)
            {
                bNeedsCompilation = RequiresCompilation(SourceFileNames, AssemblySourcesListFilePath, OutputAssemblyPath);
            }

            // Load the assembly to ensure it is correct
            Assembly CompiledAssembly = null;

            if (!bNeedsCompilation)
            {
                try
                {
                    // Load the previously-compiled assembly from disk
                    CompiledAssembly = Assembly.LoadFile(OutputAssemblyPath.FullName);
                }
                catch (FileLoadException Ex)
                {
                    Log.TraceInformation(String.Format("Unable to load the previously-compiled assembly file '{0}'.  Unreal Build Tool will try to recompile this assembly now.  (Exception: {1})", OutputAssemblyPath, Ex.Message));
                    bNeedsCompilation = true;
                }
                catch (BadImageFormatException Ex)
                {
                    Log.TraceInformation(String.Format("Compiled assembly file '{0}' appears to be for a newer CLR version or is otherwise invalid.  Unreal Build Tool will try to recompile this assembly now.  (Exception: {1})", OutputAssemblyPath, Ex.Message));
                    bNeedsCompilation = true;
                }
                catch (Exception Ex)
                {
                    throw new BuildException(Ex, "Error while loading previously-compiled assembly file '{0}'.  (Exception: {1})", OutputAssemblyPath, Ex.Message);
                }
            }

            // Compile the assembly if me
            if (bNeedsCompilation)
            {
                CompiledAssembly = CompileAssembly(OutputAssemblyPath, SourceFileNames, ReferencedAssembies, PreprocessorDefines, TreatWarningsAsErrors);

                // Save out a list of all the source files we compiled.  This is so that we can tell if whole files were added or removed
                // since the previous time we compiled the assembly.  In that case, we'll always want to recompile it!
                {
                    FileInfo AssemblySourcesListFile = new FileInfo(AssemblySourcesListFilePath.FullName);
                    using (var Writer = AssemblySourcesListFile.CreateText())
                    {
                        SourceFileNames.ForEach(x => Writer.WriteLine(x));
                    }
                }
            }

            // Load the assembly into our app domain
            try
            {
                AppDomain.CurrentDomain.Load(CompiledAssembly.GetName());
            }
            catch (Exception Ex)
            {
                throw new BuildException(Ex, "Unable to load the compiled build assembly '{0}' into our application's domain.  (Exception: {1})", OutputAssemblyPath, Ex.Message);
            }

            return(CompiledAssembly);
        }
Example #14
0
        /// <summary>
        /// Finds the header file that is referred to by a partial include filename.
        /// </summary>
        /// <param name="FromFile">The file containing the include directory</param>
        /// <param name="RelativeIncludePath">path relative to the project</param>
        /// <param name="IncludePaths">Include paths to search</param>
        public static FileItem FindIncludedFile(FileReference FromFile, string RelativeIncludePath, CppIncludePaths IncludePaths)
        {
            FileItem Result = null;

            ++TotalFindIncludedFileCalls;

            // Only search for the include file if the result hasn't been cached.
            string InvariantPath = RelativeIncludePath.ToLowerInvariant();

            if (!IncludePaths.IncludeFileSearchDictionary.TryGetValue(InvariantPath, out Result))
            {
                int SearchAttempts = 0;
                if (Path.IsPathRooted(RelativeIncludePath))
                {
                    FileReference Reference = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, RelativeIncludePath);
                    if (DirectoryLookupCache.FileExists(Reference))
                    {
                        Result = FileItem.GetItemByFileReference(Reference);
                    }
                    ++SearchAttempts;
                }
                else
                {
                    // Find the first include path that the included file exists in.
                    List <DirectoryReference> IncludePathsToSearch = IncludePaths.GetPathsToSearch(FromFile);
                    foreach (DirectoryReference IncludePath in IncludePathsToSearch)
                    {
                        ++SearchAttempts;
                        FileReference FullFilePath;
                        try
                        {
                            FullFilePath = FileReference.Combine(IncludePath, RelativeIncludePath);
                        }
                        catch (ArgumentException Exception)
                        {
                            throw new BuildException(Exception, "Failed to combine null or invalid include paths.");
                        }
                        if (DirectoryLookupCache.FileExists(FullFilePath))
                        {
                            Result = FileItem.GetItemByFileReference(FullFilePath);
                            break;
                        }
                    }
                }

                IncludePathSearchAttempts += SearchAttempts;

                if (UnrealBuildTool.bPrintPerformanceInfo)
                {
                    // More than two search attempts indicates:
                    //		- Include path was not relative to the directory that the including file was in
                    //		- Include path was not relative to the project's base
                    if (SearchAttempts > 2)
                    {
                        Log.TraceVerbose("   Cache miss: " + RelativeIncludePath + " found after " + SearchAttempts.ToString() + " attempts: " + (Result != null ? Result.AbsolutePath : "NOT FOUND!"));
                    }
                }

                // Cache the result of the include path search.
                IncludePaths.IncludeFileSearchDictionary.Add(InvariantPath, Result);
            }

            // @todo ubtmake: The old UBT tried to skip 'external' (STABLE) headers here.  But it didn't work.  We might want to do this though!  Skip system headers and source/thirdparty headers!

            if (Result != null)
            {
                Log.TraceVerbose("Resolved included file \"{0}\" to: {1}", RelativeIncludePath, Result.AbsolutePath);
            }
            else
            {
                Log.TraceVerbose("Couldn't resolve included file \"{0}\"", RelativeIncludePath);
            }

            return(Result);
        }
Example #15
0
        protected string GetDsymutilPath(out string ExtraOptions, bool bIsForLTOBuild = false)
        {
            FileReference DsymutilLocation = new FileReference("/usr/bin/dsymutil");

            // dsymutil before 10.0.1 has a bug that causes issues, it's fixed in autosdks but not everyone has those set up so for the timebeing we have
            // a version in P4 - first determine if we need it
            string DsymutilVersionString = Utils.RunLocalProcessAndReturnStdOut(DsymutilLocation.FullName, "-version");

            bool bUseInstalledDsymutil = true;
            int  Major = 0, Minor = 0, Patch = 0;

            // tease out the version number
            string[] Tokens = DsymutilVersionString.Split(" ".ToCharArray());

            // sanity check
            if (Tokens.Length < 4 || Tokens[3].Contains(".") == false)
            {
                Log.TraceInformationOnce("Unable to parse dsymutil version out of: {0}", DsymutilVersionString);
            }
            else
            {
                string[] Versions = Tokens[3].Split(".".ToCharArray());
                if (Versions.Length < 3)
                {
                    Log.TraceInformationOnce("Unable to parse version token: {0}", Tokens[3]);
                }
                else
                {
                    if (!int.TryParse(Versions[0], out Major) || !int.TryParse(Versions[1], out Minor) || !int.TryParse(Versions[2], out Patch))
                    {
                        Log.TraceInformationOnce("Unable to parse version tokens: {0}", Tokens[3]);
                    }
                    else
                    {
                        if (Major < 12)
                        {
                            Log.TraceInformationOnce("dsymutil version is {0}.{1}.{2}. Using bundled version.", Major, Minor, Patch);
                            bUseInstalledDsymutil = false;
                        }
                    }
                }
            }

            // if the installed one is too old, use a fixed up one if it can
            if (bUseInstalledDsymutil == false)
            {
                FileReference PatchedDsymutilLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries/Mac/NotForLicensees/LLVM/bin/dsymutil");

                if (File.Exists(PatchedDsymutilLocation.FullName))
                {
                    DsymutilLocation = PatchedDsymutilLocation;
                }

                DirectoryReference AutoSdkDir;
                if (UEBuildPlatformSDK.TryGetHostPlatformAutoSDKDir(out AutoSdkDir))
                {
                    FileReference AutoSdkDsymutilLocation = FileReference.Combine(AutoSdkDir, "Mac", "LLVM", "bin", "dsymutil");
                    if (FileReference.Exists(AutoSdkDsymutilLocation))
                    {
                        DsymutilLocation = AutoSdkDsymutilLocation;
                    }
                }
            }

            // 10.0.1 has an issue with LTO builds where we need to limit the number of threads
            ExtraOptions = (bIsForLTOBuild && Major == 10 && Minor == 0 && Patch == 1) ? "-j 1" : "";
            return(DsymutilLocation.FullName);
        }
Example #16
0
        /// <summary>
        /// Gets the location of the makefile for particular target
        /// </summary>
        /// <param name="ProjectFile">Project file for the build</param>
        /// <param name="TargetName">Name of the target being built</param>
        /// <param name="Platform">The platform that the target is being built for</param>
        /// <param name="Configuration">The configuration being built</param>
        /// <returns>Path to the makefile</returns>
        public static FileReference GetLocation(FileReference ProjectFile, string TargetName, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration)
        {
            DirectoryReference BaseDirectory = DirectoryReference.FromFile(ProjectFile) ?? UnrealBuildTool.EngineDirectory;

            return(FileReference.Combine(BaseDirectory, "Intermediate", "Build", Platform.ToString(), TargetName, Configuration.ToString(), "Makefile.bin"));
        }
Example #17
0
        /// <summary>
        /// Whether the path contains a valid clang version
        /// </summary>
        private static bool IsValidClangPath(DirectoryReference BaseLinuxPath)
        {
            FileReference ClangPath = FileReference.Combine(BaseLinuxPath, @"bin", (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64) ? "clang++.exe" : "clang++");

            return(FileReference.Exists(ClangPath));
        }
Example #18
0
        private static void ParsePlatformConfiguration(string PlatformConfiguration)
        {
            // Trim whitespace at the beginning.
            PlatformConfiguration = PlatformConfiguration.Trim();
            // Remove brackets.
            PlatformConfiguration = PlatformConfiguration.TrimStart('(');
            PlatformConfiguration = PlatformConfiguration.TrimEnd(')');

            bool bCanCreateEntry = true;

            string ConfigurationName;
            UnrealTargetConfiguration Configuration = UnrealTargetConfiguration.Unknown;

            if (ParseSubValue(PlatformConfiguration, "Configuration=", out ConfigurationName))
            {
                Enum.TryParse(ConfigurationName, out Configuration);
            }
            if (Configuration == UnrealTargetConfiguration.Unknown)
            {
                Log.TraceWarning("Unable to read configuration from {0}", PlatformConfiguration);
                bCanCreateEntry = false;
            }

            string PlatformName;
            UnrealTargetPlatform Platform = UnrealTargetPlatform.Unknown;

            if (ParseSubValue(PlatformConfiguration, "PlatformName=", out PlatformName))
            {
                Enum.TryParse(PlatformName, out Platform);
            }
            if (Platform == UnrealTargetPlatform.Unknown)
            {
                Log.TraceWarning("Unable to read platform from {0}", PlatformConfiguration);
                bCanCreateEntry = false;
            }

            string     PlatformTypeName;
            TargetType PlatformType = TargetType.Game;

            if (ParseSubValue(PlatformConfiguration, "PlatformTypeName=", out PlatformTypeName))
            {
                if (!Enum.TryParse(PlatformTypeName, out PlatformType))
                {
                    Log.TraceWarning("Unable to read Platform Type from {0}, defaulting to Game", PlatformConfiguration);
                    PlatformType = TargetType.Game;
                }
            }
            if (PlatformType == TargetType.Program)
            {
                Log.TraceWarning("Program is not a valid PlatformType for an Installed Platform, defaulting to Game");
                PlatformType = TargetType.Game;
            }

            string Architecture;

            ParseSubValue(PlatformConfiguration, "Architecture=", out Architecture);

            string RequiredFile;

            if (ParseSubValue(PlatformConfiguration, "RequiredFile=", out RequiredFile))
            {
                RequiredFile = FileReference.Combine(UnrealBuildTool.RootDirectory, RequiredFile).ToString();
            }

            string       ProjectTypeName;
            EProjectType ProjectType = EProjectType.Any;

            if (ParseSubValue(PlatformConfiguration, "ProjectType=", out ProjectTypeName))
            {
                Enum.TryParse(ProjectTypeName, out ProjectType);
            }
            if (ProjectType == EProjectType.Unknown)
            {
                Log.TraceWarning("Unable to read project type from {0}", PlatformConfiguration);
                bCanCreateEntry = false;
            }

            string CanBeDisplayedString;
            bool   bCanBeDisplayed = false;

            if (ParseSubValue(PlatformConfiguration, "bCanBeDisplayed=", out CanBeDisplayedString))
            {
                bCanBeDisplayed = Convert.ToBoolean(CanBeDisplayedString);
            }

            if (bCanCreateEntry)
            {
                InstalledPlatformConfigurations.Add(new InstalledPlatformConfiguration(Configuration, Platform, PlatformType, Architecture, RequiredFile, ProjectType, bCanBeDisplayed));
            }
        }
Example #19
0
        internal bool ExecuteActions(List <Action> InActions, Dictionary <Action, ActionThread> InActionThreadDictionary)
        {
            // Build the script file that will be executed by SN-DBS
            StreamWriter ScriptFile;
            string       ScriptFilename = Path.Combine(UnrealBuildTool.EngineDirectory.FullName, "Intermediate", "Build", "SNDBS.bat");

            FileStream ScriptFileStream = new FileStream(ScriptFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);

            ScriptFile           = new StreamWriter(ScriptFileStream);
            ScriptFile.AutoFlush = true;

            int           NumScriptedActions = 0;
            List <Action> LocalActions       = new List <Action>();
            ActionThread  DummyActionThread  = new ActionThread(null, 1, 1);

            foreach (Action Action in InActions)
            {
                ActionThread ActionProcess       = null;
                bool         bFoundActionProcess = InActionThreadDictionary.TryGetValue(Action, out ActionProcess);
                if (bFoundActionProcess == false)
                {
                    // Determine whether there are any prerequisites of the action that are outdated.
                    bool bHasOutdatedPrerequisites = false;
                    bool bHasFailedPrerequisites   = false;
                    foreach (FileItem PrerequisiteItem in Action.PrerequisiteItems)
                    {
                        if (PrerequisiteItem.ProducingAction != null && InActions.Contains(PrerequisiteItem.ProducingAction))
                        {
                            ActionThread PrerequisiteProcess       = null;
                            bool         bFoundPrerequisiteProcess = InActionThreadDictionary.TryGetValue(PrerequisiteItem.ProducingAction, out PrerequisiteProcess);
                            if (bFoundPrerequisiteProcess == true)
                            {
                                if (PrerequisiteProcess == null)
                                {
                                    bHasFailedPrerequisites = true;
                                }
                                else if (PrerequisiteProcess.bComplete == false)
                                {
                                    bHasOutdatedPrerequisites = true;
                                }
                                else if (PrerequisiteProcess.ExitCode != 0)
                                {
                                    bHasFailedPrerequisites = true;
                                }
                            }
                            else
                            {
                                bHasOutdatedPrerequisites = true;
                            }
                        }
                    }

                    // If there are any failed prerequisites of this action, don't execute it.
                    if (bHasFailedPrerequisites)
                    {
                        // Add a null entry in the dictionary for this action.
                        InActionThreadDictionary.Add(Action, null);
                    }
                    // If there aren't any outdated prerequisites of this action, execute it.
                    else if (!bHasOutdatedPrerequisites)
                    {
                        if (Action.bCanExecuteRemotely == false || Action.bCanExecuteRemotelyWithSNDBS == false)
                        {
                            // Execute locally
                            LocalActions.Add(Action);
                        }
                        else
                        {
                            // Add to script for execution by SN-DBS
                            string NewCommandArguments = "\"" + Action.CommandPath + "\"" + " " + Action.CommandArguments;
                            ScriptFile.WriteLine(ActionThread.ExpandEnvironmentVariables(NewCommandArguments));
                            InActionThreadDictionary.Add(Action, DummyActionThread);
                            Action.StartTime = Action.EndTime = DateTimeOffset.Now;
                            Log.TraceInformation("[{0}/{1}] {2} {3}", JobNumber, InActions.Count, Action.CommandDescription, Action.StatusDescription);
                            JobNumber++;
                            NumScriptedActions++;
                        }
                    }
                }
            }

            ScriptFile.Flush();
            ScriptFile.Close();
            ScriptFile.Dispose();
            ScriptFile = null;

            if (NumScriptedActions > 0)
            {
                // Create the process
                string           SCERoot         = Environment.GetEnvironmentVariable("SCE_ROOT_DIR");
                string           SNDBSExecutable = Path.Combine(SCERoot, "Common/SN-DBS/bin/dbsbuild.exe");
                ProcessStartInfo PSI             = new ProcessStartInfo(SNDBSExecutable, String.Format("-q -p UE4 -s \"{0}\"", FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "sndbs.bat").FullName));
                PSI.RedirectStandardOutput = true;
                PSI.RedirectStandardError  = true;
                PSI.UseShellExecute        = false;
                PSI.CreateNoWindow         = true;
                PSI.WorkingDirectory       = Path.GetFullPath(".");;
                Process NewProcess = new Process();
                NewProcess.StartInfo           = PSI;
                NewProcess.OutputDataReceived += new DataReceivedEventHandler(ActionDebugOutput);
                NewProcess.ErrorDataReceived  += new DataReceivedEventHandler(ActionDebugOutput);
                DateTimeOffset StartTime = DateTimeOffset.Now;
                NewProcess.Start();
                NewProcess.BeginOutputReadLine();
                NewProcess.BeginErrorReadLine();

                NewProcess.WaitForExit();

                TimeSpan       Duration;
                DateTimeOffset EndTime = DateTimeOffset.Now;
                if (EndTime == DateTimeOffset.MinValue)
                {
                    Duration = DateTimeOffset.Now - StartTime;
                }
                else
                {
                    Duration = EndTime - StartTime;
                }

                DummyActionThread.bComplete = true;
                int ExitCode = NewProcess.ExitCode;
                if (ExitCode != 0)
                {
                    return(false);
                }
            }

            // Execute local tasks
            if (LocalActions.Count > 0)
            {
                return(ExecuteLocalActions(LocalActions, InActionThreadDictionary, InActions.Count));
            }

            return(true);
        }
        /// <summary>
        /// For additional Project file *PROJECTNAME*-AndroidRun.androidproj that needs to be written out.  This is currently used only on Android.
        /// </summary>
        /// <param name="ProjectFile">ProjectFile object</param>
        public override Tuple <ProjectFile, string> WriteAdditionalProjFile(ProjectFile ProjectFile)
        {
            if (!IsVSAndroidSupportInstalled())
            {
                return(null);
            }

            string ProjectName = ProjectFile.ProjectFilePath.GetFileNameWithoutExtension() + "-AndroidRun";

            string FileName = ProjectName + ".androidproj";

            string FileText = "<?xml version=\"1.0\" encoding=\"utf-8\"?> " + ProjectFileGenerator.NewLine +
                              "<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"> " + ProjectFileGenerator.NewLine +
                              "	<ItemGroup Label=\"ProjectConfigurations\"> " + ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Debug|ARM\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Debug</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>ARM</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Release|ARM\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Release</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>ARM</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Debug|ARM64\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Debug</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>ARM64</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Release|ARM64\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Release</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>ARM64</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Debug|x64\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Debug</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>x64</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Release|x64\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Release</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>x64</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Debug|x86\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Debug</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>x86</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectConfiguration Include=\"Release|x86\"> "+ ProjectFileGenerator.NewLine +
                              "			<Configuration>Release</Configuration> "+ ProjectFileGenerator.NewLine +
                              "			<Platform>x86</Platform> "+ ProjectFileGenerator.NewLine +
                              "		</ProjectConfiguration> "+ ProjectFileGenerator.NewLine +
                              "	</ItemGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Label=\"Globals\"> " + ProjectFileGenerator.NewLine +
                              "		<RootNamespace>"+ ProjectName + "</RootNamespace> " + ProjectFileGenerator.NewLine +
                              "		<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> "+ ProjectFileGenerator.NewLine +
                              "		<ProjectVersion>1.0</ProjectVersion> "+ ProjectFileGenerator.NewLine +

                              //Set the project guid
                              "		<ProjectGuid>"+ System.Guid.NewGuid().ToString("B").ToUpper() + "</ProjectGuid> " + ProjectFileGenerator.NewLine +

                              "		<ConfigurationType>Application</ConfigurationType> "+ ProjectFileGenerator.NewLine +
                              "		<_PackagingProjectWithoutNativeComponent>true</_PackagingProjectWithoutNativeComponent> "+ ProjectFileGenerator.NewLine +
                              "		<LaunchActivity Condition=\"\'$(LaunchActivity)\' == \'\'\">com."+ ProjectName + "." + ProjectName + "</LaunchActivity> " + ProjectFileGenerator.NewLine +
                              "		<JavaSourceRoots>src</JavaSourceRoots> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<Import Project=\"$(AndroidTargetsPath)\\Android.Default.props\" /> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>true</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>false</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM64\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>true</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM64\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>false</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x64\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>true</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x64\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>false</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x86\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>true</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x86\'\" Label=\"Configuration\"> " + ProjectFileGenerator.NewLine +
                              "		<UseDebugLibraries>false</UseDebugLibraries> "+ ProjectFileGenerator.NewLine +
                              "		<TargetName>$(RootNamespace)</TargetName> "+ ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<Import Project=\"$(AndroidTargetsPath)\\Android.props\" /> " + ProjectFileGenerator.NewLine +
                              "	<ImportGroup Label=\"ExtensionSettings\" /> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Label=\"UserMacros\" /> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM64\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM64\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x64\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x64\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x86\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<PropertyGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x86\'\"> " + ProjectFileGenerator.NewLine +
                              "	</PropertyGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|ARM64\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|ARM64\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x64\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x64\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Debug|x86\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<ItemDefinitionGroup Condition=\"\'$(Configuration)|$(Platform)\'==\'Release|x86\'\"> " + ProjectFileGenerator.NewLine +
                              "		<AntPackage> "+ ProjectFileGenerator.NewLine +
                              "			<AndroidAppLibName /> "+ ProjectFileGenerator.NewLine +
                              "		</AntPackage> "+ ProjectFileGenerator.NewLine +
                              "	</ItemDefinitionGroup> " + ProjectFileGenerator.NewLine +
                              "	<Import Project=\"$(AndroidTargetsPath)\\Android.targets\" /> " + ProjectFileGenerator.NewLine +
                              "	<ImportGroup Label=\"ExtensionTargets\" /> " + ProjectFileGenerator.NewLine +
                              "</Project>";

            bool Success = ProjectFileGenerator.WriteFileIfChanged(ProjectFileGenerator.IntermediateProjectFilesPath + "\\" + FileName, FileText);

            FileReference           ProjectFilePath = FileReference.Combine(ProjectFileGenerator.IntermediateProjectFilesPath, FileName);
            AndroidDebugProjectFile Project         = new AndroidDebugProjectFile(ProjectFilePath);

            Project.ShouldBuildForAllSolutionTargets       = false;
            Project.ShouldBuildByDefaultForSolutionTargets = false;

            return(Success ? new Tuple <ProjectFile, string>(Project, "UE4 Android Debug Projects") : null);
        }
Example #21
0
        private LinkEnvironment SetupBinaryLinkEnvironment(ReadOnlyTargetRules Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CppCompileEnvironment CompileEnvironment, ISourceFileWorkingSet WorkingSet, DirectoryReference ExeDir, TargetMakefile Makefile)
        {
            LinkEnvironment         BinaryLinkEnvironment         = new LinkEnvironment(LinkEnvironment);
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CppCompileEnvironment BinaryCompileEnvironment = CreateBinaryCompileEnvironment(CompileEnvironment);

            if (BinaryCompileEnvironment.bUseSharedBuildEnvironment && Target.ProjectFile != null && IntermediateDirectory.IsUnderDirectory(Target.ProjectFile.Directory))
            {
                BinaryCompileEnvironment.bUseSharedBuildEnvironment = false;
            }

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, WorkingSet, Makefile);

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }

                    // Force a reference to initialize module for this binary
                    if (Module.Rules.bRequiresImplementModule.Value)
                    {
                        BinaryLinkEnvironment.IncludeFunctions.Add(String.Format("IMPLEMENT_MODULE_{0}", Module.Name));
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                // Allow the module to modify the link environment for the binary.
                Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules, ExeDir);
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Set the link output file.
            BinaryLinkEnvironment.OutputFilePaths = OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.bHasExports = bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.IntermediateDirectory = IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.OutputDirectory = OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.bIsBuildingDLL     = IsBuildingDll(Type);
            BinaryLinkEnvironment.bIsBuildingLibrary = IsBuildingLibrary(Type);

            // If we don't have any resource file, use the default or compile a custom one for this module
            if (BinaryLinkEnvironment.Platform == UnrealTargetPlatform.Win32 || BinaryLinkEnvironment.Platform == UnrealTargetPlatform.Win64)
            {
                // Figure out if this binary has any custom resource files. Hacky check to ignore the resource file in the Launch module, since it contains dialogs that the engine needs and always needs to be included.
                FileItem[] CustomResourceFiles = BinaryLinkEnvironment.InputFiles.Where(x => x.Location.HasExtension(".res") && !x.Location.FullName.EndsWith("\\Launch\\PCLaunch.rc.res", StringComparison.OrdinalIgnoreCase)).ToArray();
                if (CustomResourceFiles.Length == 0)
                {
                    if (BinaryLinkEnvironment.DefaultResourceFiles.Count > 0)
                    {
                        // Use the default resource file if possible
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                    else
                    {
                        // Get the intermediate directory
                        DirectoryReference ResourceIntermediateDirectory = BinaryLinkEnvironment.IntermediateDirectory;

                        // Create a compile environment for resource files
                        CppCompileEnvironment ResourceCompileEnvironment = new CppCompileEnvironment(BinaryCompileEnvironment);

                        // @todo: This should be in some Windows code somewhere...
                        // Set the original file name macro; used in Default.rc2 to set the binary metadata fields.
                        ResourceCompileEnvironment.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OutputFilePaths[0].GetFileName() + "\"");

                        // Set the other version fields
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILT_FROM_CHANGELIST={0}", Target.Version.Changelist));
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILD_VERSION={0}", Target.BuildVersion));

                        // Otherwise compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Windows", "Resources", "Default.rc2"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(ResourceCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ResourceIntermediateDirectory, Makefile.Actions);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                }
            }

            // Add all the common resource files
            BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);

            return(BinaryLinkEnvironment);
        }
        /// <summary>
        /// Write a Module to a JSON writer. If array is empty, don't write anything
        /// </summary>
        /// <param name="BinaryOutputDir"></param>
        /// <param name="TargetOutputDir"></param>
        /// <param name="Writer">Writer for the array data</param>
        /// <param name="Module"></param>
        private static void ExportModule(UEBuildModule Module, DirectoryReference BinaryOutputDir, DirectoryReference TargetOutputDir, JsonWriter Writer)
        {
            Writer.WriteValue("Name", Module.Name);
            Writer.WriteValue("Directory", Module.ModuleDirectory.FullName);
            Writer.WriteValue("Rules", Module.RulesFile.FullName);
            Writer.WriteValue("PCHUsage", Module.Rules.PCHUsage.ToString());

            if (Module.Rules.PrivatePCHHeaderFile != null)
            {
                Writer.WriteValue("PrivatePCH", FileReference.Combine(Module.ModuleDirectory, Module.Rules.PrivatePCHHeaderFile).FullName);
            }

            if (Module.Rules.SharedPCHHeaderFile != null)
            {
                Writer.WriteValue("SharedPCH", FileReference.Combine(Module.ModuleDirectory, Module.Rules.SharedPCHHeaderFile).FullName);
            }

            ExportJsonModuleArray(Writer, "PublicDependencyModules", Module.PublicDependencyModules);
            ExportJsonModuleArray(Writer, "PublicIncludePathModules", Module.PublicIncludePathModules);
            ExportJsonModuleArray(Writer, "PrivateDependencyModules", Module.PrivateDependencyModules);
            ExportJsonModuleArray(Writer, "PrivateIncludePathModules", Module.PrivateIncludePathModules);
            ExportJsonModuleArray(Writer, "DynamicallyLoadedModules", Module.DynamicallyLoadedModules);

            ExportJsonStringArray(Writer, "PublicSystemIncludePaths", Module.PublicSystemIncludePaths.Select(x => x.FullName));
            ExportJsonStringArray(Writer, "PublicIncludePaths", Module.PublicIncludePaths.Select(x => x.FullName));

            ExportJsonStringArray(Writer, "LegacyPublicIncludePaths", Module.LegacyPublicIncludePaths.Select(x => x.FullName));

            ExportJsonStringArray(Writer, "PrivateIncludePaths", Module.PrivateIncludePaths.Select(x => x.FullName));
            ExportJsonStringArray(Writer, "PublicLibraryPaths", Module.PublicSystemLibraryPaths.Select(x => x.FullName));
            ExportJsonStringArray(Writer, "PublicAdditionalLibraries", Module.PublicSystemLibraries.Concat(Module.PublicAdditionalLibraries));
            ExportJsonStringArray(Writer, "PublicFrameworks", Module.PublicFrameworks);
            ExportJsonStringArray(Writer, "PublicWeakFrameworks", Module.PublicWeakFrameworks);
            ExportJsonStringArray(Writer, "PublicDelayLoadDLLs", Module.PublicDelayLoadDLLs);
            ExportJsonStringArray(Writer, "PublicDefinitions", Module.PublicDefinitions);
            ExportJsonStringArray(Writer, "PrivateDefinitions", Module.Rules.PrivateDefinitions);
            ExportJsonStringArray(Writer, "ProjectDefinitions", /* TODO: Add method ShouldAddProjectDefinitions */ !Module.Rules.bTreatAsEngineModule ? Module.Rules.Target.ProjectDefinitions : new string[0]);
            ExportJsonStringArray(Writer, "ApiDefinitions", Module.GetEmptyApiMacros());
            Writer.WriteValue("ShouldAddLegacyPublicIncludePaths", Module.Rules.bLegacyPublicIncludePaths);

            if (Module.Rules.CircularlyReferencedDependentModules.Any())
            {
                Writer.WriteArrayStart("CircularlyReferencedModules");
                foreach (string ModuleName in Module.Rules.CircularlyReferencedDependentModules)
                {
                    Writer.WriteValue(ModuleName);
                }
                Writer.WriteArrayEnd();
            }

            if (Module.Rules.RuntimeDependencies.Inner.Any())
            {
                // We don't use info from RuntimeDependencies for code analyzes (at the moment)
                // So we're OK with skipping some values if they are not presented
                Writer.WriteArrayStart("RuntimeDependencies");
                foreach (ModuleRules.RuntimeDependency RuntimeDependency in Module.Rules.RuntimeDependencies.Inner)
                {
                    Writer.WriteObjectStart();

                    try
                    {
                        Writer.WriteValue("Path",
                                          Module.ExpandPathVariables(RuntimeDependency.Path, BinaryOutputDir, TargetOutputDir));
                    }
                    catch (BuildException buildException)
                    {
                        Log.TraceVerbose("Value {0} for module {1} will not be stored. Reason: {2}", "Path", Module.Name, buildException);
                    }

                    if (RuntimeDependency.SourcePath != null)
                    {
                        try
                        {
                            Writer.WriteValue("SourcePath",
                                              Module.ExpandPathVariables(RuntimeDependency.SourcePath, BinaryOutputDir,
                                                                         TargetOutputDir));
                        }
                        catch (BuildException buildException)
                        {
                            Log.TraceVerbose("Value {0} for module {1} will not be stored. Reason: {2}", "SourcePath", Module.Name, buildException);
                        }
                    }

                    Writer.WriteValue("Type", RuntimeDependency.Type.ToString());

                    Writer.WriteObjectEnd();
                }
                Writer.WriteArrayEnd();
            }
        }
Example #23
0
        /// <summary>
        /// Build a target remotely
        /// </summary>
        /// <param name="TargetDesc">Descriptor for the target to build</param>
        /// <param name="RemoteLogFile">Path to store the remote log file</param>
        /// <returns>True if the build succeeded, false otherwise</returns>
        public bool Build(TargetDescriptor TargetDesc, FileReference RemoteLogFile)
        {
            // Get the directory for working files
            DirectoryReference BaseDir = DirectoryReference.FromFile(TargetDesc.ProjectFile) ?? UnrealBuildTool.EngineDirectory;
            DirectoryReference TempDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Remote", TargetDesc.Name, TargetDesc.Platform.ToString(), TargetDesc.Configuration.ToString());

            DirectoryReference.CreateDirectory(TempDir);

            bool bLogIsMapped = false;

            foreach (RemoteMapping Mapping in Mappings)
            {
                if (RemoteLogFile.Directory.FullName.Equals(Mapping.LocalDirectory.FullName, StringComparison.InvariantCultureIgnoreCase))
                {
                    bLogIsMapped = true;
                    break;
                }
            }
            if (!bLogIsMapped)
            {
                Mappings.Add(new RemoteMapping(RemoteLogFile.Directory, GetRemotePath(RemoteLogFile.Directory)));
            }

            // Compile the rules assembly
            RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDesc.ProjectFile, TargetDesc.Name, false, false, TargetDesc.ForeignPlugin);

            // Create the target rules
            TargetRules Rules = RulesAssembly.CreateTargetRules(TargetDesc.Name, TargetDesc.Platform, TargetDesc.Configuration, TargetDesc.Architecture, TargetDesc.ProjectFile, new ReadOnlyBuildVersion(BuildVersion.ReadDefault()), new string[0]);

            // Check if we need to enable a nativized plugin, and compile the assembly for that if we do
            FileReference NativizedPluginFile = Rules.GetNativizedPlugin();

            if (NativizedPluginFile != null)
            {
                RulesAssembly = RulesCompiler.CreatePluginRulesAssembly(NativizedPluginFile, false, RulesAssembly, false);
            }

            // Path to the local manifest file. This has to be translated from the remote format after the build is complete.
            List <FileReference> LocalManifestFiles = new List <FileReference>();

            // Path to the remote manifest file
            FileReference RemoteManifestFile = FileReference.Combine(TempDir, "Manifest.xml");

            // Prepare the arguments we will pass to the remote build
            List <string> RemoteArguments = new List <string>();

            RemoteArguments.Add(TargetDesc.Name);
            RemoteArguments.Add(TargetDesc.Platform.ToString());
            RemoteArguments.Add(TargetDesc.Configuration.ToString());
            RemoteArguments.Add("-SkipRulesCompile");                                                      // Use the rules assembly built locally
            RemoteArguments.Add(String.Format("-XmlConfigCache={0}", GetRemotePath(XmlConfig.CacheFile))); // Use the XML config cache built locally, since the remote won't have it
            RemoteArguments.Add(String.Format("-Log={0}", GetRemotePath(RemoteLogFile)));
            RemoteArguments.Add(String.Format("-Manifest={0}", GetRemotePath(RemoteManifestFile)));

            if (TargetDesc.ProjectFile != null)
            {
                RemoteArguments.Add(String.Format("-Project={0}", GetRemotePath(TargetDesc.ProjectFile)));
            }

            foreach (string LocalArgument in TargetDesc.AdditionalArguments)
            {
                int EqualsIdx = LocalArgument.IndexOf('=');
                if (EqualsIdx == -1)
                {
                    RemoteArguments.Add(LocalArgument);
                    continue;
                }

                string Key   = LocalArgument.Substring(0, EqualsIdx);
                string Value = LocalArgument.Substring(EqualsIdx + 1);

                if (Key.Equals("-Log", StringComparison.InvariantCultureIgnoreCase))
                {
                    // We are already writing to the local log file. The remote will produce a different log (RemoteLogFile)
                    continue;
                }
                if (Key.Equals("-Manifest", StringComparison.InvariantCultureIgnoreCase))
                {
                    LocalManifestFiles.Add(new FileReference(Value));
                    continue;
                }

                string RemoteArgument = LocalArgument;
                foreach (RemoteMapping Mapping in Mappings)
                {
                    if (Value.StartsWith(Mapping.LocalDirectory.FullName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        RemoteArgument = String.Format("{0}={1}", Key, GetRemotePath(Value));
                        break;
                    }
                }
                RemoteArguments.Add(RemoteArgument);
            }

            // Handle any per-platform setup that is required
            if (TargetDesc.Platform == UnrealTargetPlatform.IOS || TargetDesc.Platform == UnrealTargetPlatform.TVOS)
            {
                // Always generate a .stub
                RemoteArguments.Add("-CreateStub");

                // Cannot use makefiles, since we need PostBuildSync() to generate the IPA (and that requires a TargetRules instance)
                RemoteArguments.Add("-NoUBTMakefiles");

                // Get the provisioning data for this project
                IOSProvisioningData ProvisioningData = ((IOSPlatform)UEBuildPlatform.GetBuildPlatform(TargetDesc.Platform)).ReadProvisioningData(TargetDesc.ProjectFile);
                if (ProvisioningData == null || ProvisioningData.MobileProvisionFile == null)
                {
                    throw new BuildException("Unable to find mobile provision for {0}. See log for more information.", TargetDesc.Name);
                }

                // Create a local copy of the provision
                FileReference MobileProvisionFile = FileReference.Combine(TempDir, ProvisioningData.MobileProvisionFile.GetFileName());
                if (FileReference.Exists(MobileProvisionFile))
                {
                    FileReference.SetAttributes(MobileProvisionFile, FileAttributes.Normal);
                }
                FileReference.Copy(ProvisioningData.MobileProvisionFile, MobileProvisionFile, true);
                Log.TraceInformation("[Remote] Uploading {0}", MobileProvisionFile);
                UploadFile(MobileProvisionFile);

                // Extract the certificate for the project. Try to avoid calling IPP if we already have it.
                FileReference CertificateFile = FileReference.Combine(TempDir, "Certificate.p12");

                FileReference CertificateInfoFile     = FileReference.Combine(TempDir, "Certificate.txt");
                string        CertificateInfoContents = String.Format("{0}\n{1}", ProvisioningData.MobileProvisionFile, FileReference.GetLastWriteTimeUtc(ProvisioningData.MobileProvisionFile).Ticks);

                if (!FileReference.Exists(CertificateFile) || !FileReference.Exists(CertificateInfoFile) || FileReference.ReadAllText(CertificateInfoFile) != CertificateInfoContents)
                {
                    Log.TraceInformation("[Remote] Exporting certificate for {0}...", ProvisioningData.MobileProvisionFile);

                    StringBuilder Arguments = new StringBuilder("ExportCertificate");
                    if (TargetDesc.ProjectFile == null)
                    {
                        Arguments.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineSourceDirectory);
                    }
                    else
                    {
                        Arguments.AppendFormat(" \"{0}\"", TargetDesc.ProjectFile.Directory);
                    }
                    Arguments.AppendFormat(" -provisionfile \"{0}\"", ProvisioningData.MobileProvisionFile);
                    Arguments.AppendFormat(" -outputcertificate \"{0}\"", CertificateFile);
                    if (TargetDesc.Platform == UnrealTargetPlatform.TVOS)
                    {
                        Arguments.Append(" -tvos");
                    }

                    ProcessStartInfo StartInfo = new ProcessStartInfo();
                    StartInfo.FileName  = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "DotNET", "IOS", "IPhonePackager.exe").FullName;
                    StartInfo.Arguments = Arguments.ToString();
                    if (Utils.RunLocalProcessAndLogOutput(StartInfo) != 0)
                    {
                        throw new BuildException("IphonePackager failed.");
                    }

                    FileReference.WriteAllText(CertificateInfoFile, CertificateInfoContents);
                }

                // Upload the certificate to the remote
                Log.TraceInformation("[Remote] Uploading {0}", CertificateFile);
                UploadFile(CertificateFile);

                // Tell the remote UBT instance to use them
                RemoteArguments.Add(String.Format("-ImportProvision={0}", GetRemotePath(MobileProvisionFile)));
                RemoteArguments.Add(String.Format("-ImportCertificate={0}", GetRemotePath(CertificateFile)));
                RemoteArguments.Add(String.Format("-ImportCertificatePassword=A"));
            }

            // Upload the workspace files
            UploadWorkspace(TempDir);

            // Fixup permissions on any shell scripts
            Execute(RemoteBaseDir, String.Format("chmod +x {0}/Build/BatchFiles/Mac/*.sh", EscapeShellArgument(GetRemotePath(UnrealBuildTool.EngineDirectory))));

            // Execute the compile
            Log.TraceInformation("[Remote] Executing build");

            StringBuilder BuildCommandLine = new StringBuilder("Engine/Build/BatchFiles/Mac/Build.sh");

            foreach (string RemoteArgument in RemoteArguments)
            {
                BuildCommandLine.AppendFormat(" {0}", EscapeShellArgument(RemoteArgument));
            }

            int Result = Execute(GetRemotePath(UnrealBuildTool.RootDirectory), BuildCommandLine.ToString());

            if (Result != 0)
            {
                if (RemoteLogFile != null)
                {
                    Log.TraceInformation("[Remote] Downloading {0}", RemoteLogFile);
                    DownloadFile(RemoteLogFile);
                }
                return(false);
            }

            // Download the manifest
            Log.TraceInformation("[Remote] Downloading {0}", RemoteManifestFile);
            DownloadFile(RemoteManifestFile);

            // Convert the manifest to local form
            BuildManifest Manifest = Utils.ReadClass <BuildManifest>(RemoteManifestFile.FullName);

            for (int Idx = 0; Idx < Manifest.BuildProducts.Count; Idx++)
            {
                Manifest.BuildProducts[Idx] = GetLocalPath(Manifest.BuildProducts[Idx]).FullName;
            }

            // Download the files from the remote
            if (TargetDesc.AdditionalArguments.Any(x => x.Equals("-GenerateManifest", StringComparison.InvariantCultureIgnoreCase)))
            {
                LocalManifestFiles.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "Manifest.xml"));
            }
            else
            {
                Log.TraceInformation("[Remote] Downloading build products");

                List <FileReference> FilesToDownload = new List <FileReference>();
                FilesToDownload.Add(RemoteLogFile);
                FilesToDownload.AddRange(Manifest.BuildProducts.Select(x => new FileReference(x)));
                DownloadFiles(FilesToDownload);
            }

            // Write out all the local manifests
            foreach (FileReference LocalManifestFile in LocalManifestFiles)
            {
                Log.TraceInformation("[Remote] Writing {0}", LocalManifestFile);
                Utils.WriteClass <BuildManifest>(Manifest, LocalManifestFile.FullName, "");
            }
            return(true);
        }
        /// <summary>
        /// Write project file info in JSON file.
        /// For every combination of <c>UnrealTargetPlatform</c>, <c>UnrealTargetConfiguration</c> and <c>TargetType</c>
        /// will be generated separate JSON file.
        /// Project file will be stored:
        /// For UE4:  {UE4Root}/Engine/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// For game: {GameRoot}/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// </summary>
        /// <remarks>
        /// * <c>UnrealTargetPlatform.Win32</c> will be always ignored.
        /// * <c>TargetType.Editor</c> will be generated for current platform only and will ignore <c>UnrealTargetConfiguration.Test</c> and <c>UnrealTargetConfiguration.Shipping</c> configurations
        /// * <c>TargetType.Program</c>  will be generated for current platform only and <c>UnrealTargetConfiguration.Development</c> configuration only
        /// </remarks>
        /// <param name="InPlatforms"></param>
        /// <param name="InConfigurations"></param>
        /// <param name="PlatformProjectGenerators"></param>
        /// <returns></returns>
        public override bool WriteProjectFile(List <UnrealTargetPlatform> InPlatforms,
                                              List <UnrealTargetConfiguration> InConfigurations,
                                              PlatformProjectGeneratorCollection PlatformProjectGenerators)
        {
            string             ProjectName       = ProjectFilePath.GetFileNameWithoutAnyExtensions();
            DirectoryReference ProjectRootFolder = DirectoryReference.Combine(RootPath, ".Rider");
            List <Tuple <FileReference, UEBuildTarget> > FileToTarget = new List <Tuple <FileReference, UEBuildTarget> >();

            foreach (UnrealTargetPlatform Platform in InPlatforms)
            {
                foreach (UnrealTargetConfiguration Configuration in InConfigurations)
                {
                    foreach (ProjectTarget ProjectTarget in ProjectTargets)
                    {
                        if (TargetTypes.Any() && !TargetTypes.Contains(ProjectTarget.TargetRules.Type))
                        {
                            continue;
                        }

                        // Skip Programs for all configs except for current platform + Development configuration
                        if (ProjectTarget.TargetRules.Type == TargetType.Program && (BuildHostPlatform.Current.Platform != Platform || Configuration != UnrealTargetConfiguration.Development))
                        {
                            continue;
                        }

                        // Skip Editor for all platforms except for current platform
                        if (ProjectTarget.TargetRules.Type == TargetType.Editor && (BuildHostPlatform.Current.Platform != Platform || (Configuration == UnrealTargetConfiguration.Test || Configuration == UnrealTargetConfiguration.Shipping)))
                        {
                            continue;
                        }

                        DirectoryReference ConfigurationFolder = DirectoryReference.Combine(ProjectRootFolder, Platform.ToString(), Configuration.ToString());

                        DirectoryReference TargetFolder =
                            DirectoryReference.Combine(ConfigurationFolder, ProjectTarget.TargetRules.Type.ToString());

                        string DefaultArchitecture = UEBuildPlatform
                                                     .GetBuildPlatform(Platform)
                                                     .GetDefaultArchitecture(ProjectTarget.UnrealProjectFilePath);
                        TargetDescriptor TargetDesc = new TargetDescriptor(ProjectTarget.UnrealProjectFilePath, ProjectTarget.Name,
                                                                           Platform, Configuration, DefaultArchitecture, Arguments);
                        try
                        {
                            UEBuildTarget BuildTarget = UEBuildTarget.Create(TargetDesc, false, false);

                            FileReference OutputFile = FileReference.Combine(TargetFolder, $"{ProjectName}.json");
                            FileToTarget.Add(Tuple.Create(OutputFile, BuildTarget));
                        }
                        catch (Exception Ex)
                        {
                            Log.TraceWarning("Exception while generating include data for Target:{0}, Platform: {1}, Configuration: {2}", TargetDesc.Name, Platform.ToString(), Configuration.ToString());
                            Log.TraceWarning(Ex.ToString());
                        }
                    }
                }
            }
            foreach (Tuple <FileReference, UEBuildTarget> tuple in FileToTarget)
            {
                SerializeTarget(tuple.Item1, tuple.Item2);
            }

            return(true);
        }
Example #25
0
        internal bool ExecuteActions(List <Action> InActions, Dictionary <Action, ActionThread> InActionThreadDictionary)
        {
            // Build the script file that will be executed by SN-DBS
            StreamWriter ScriptFile;
            string       ScriptFilename = Path.Combine(UnrealBuildTool.EngineDirectory.FullName, "Intermediate", "Build", "SNDBS.bat");

            FileStream ScriptFileStream = new FileStream(ScriptFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);

            ScriptFile           = new StreamWriter(ScriptFileStream);
            ScriptFile.AutoFlush = true;

            int           NumScriptedActions = 0;
            List <Action> LocalActions       = new List <Action>();
            ActionThread  DummyActionThread  = new ActionThread(null, 1, 1);
            bool          PrintDebugInfo     = false;

            foreach (Action Action in InActions)
            {
                ActionThread ActionProcess       = null;
                bool         bFoundActionProcess = InActionThreadDictionary.TryGetValue(Action, out ActionProcess);
                if (bFoundActionProcess == false)
                {
                    // Determine whether there are any prerequisites of the action that are outdated.
                    bool bHasOutdatedPrerequisites = false;
                    bool bHasFailedPrerequisites   = false;
                    foreach (Action PrerequisiteAction in Action.PrerequisiteActions)
                    {
                        if (InActions.Contains(PrerequisiteAction))
                        {
                            ActionThread PrerequisiteProcess       = null;
                            bool         bFoundPrerequisiteProcess = InActionThreadDictionary.TryGetValue(PrerequisiteAction, out PrerequisiteProcess);
                            if (bFoundPrerequisiteProcess == true)
                            {
                                if (PrerequisiteProcess == null)
                                {
                                    bHasFailedPrerequisites = true;
                                }
                                else if (PrerequisiteProcess.bComplete == false)
                                {
                                    bHasOutdatedPrerequisites = true;
                                }
                                else if (PrerequisiteProcess.ExitCode != 0)
                                {
                                    bHasFailedPrerequisites = true;
                                }
                            }
                            else
                            {
                                bHasOutdatedPrerequisites = true;
                            }
                        }
                    }

                    // If there are any failed prerequisites of this action, don't execute it.
                    if (bHasFailedPrerequisites)
                    {
                        // Add a null entry in the dictionary for this action.
                        InActionThreadDictionary.Add(Action, null);
                    }
                    // If there aren't any outdated prerequisites of this action, execute it.
                    else if (!bHasOutdatedPrerequisites)
                    {
                        if (Action.bCanExecuteRemotely == false || Action.bCanExecuteRemotelyWithSNDBS == false)
                        {
                            // Execute locally
                            LocalActions.Add(Action);
                        }
                        else
                        {
                            // Create a dummy force-included file which references PCH files, so that SN-DBS knows they are dependencies.
                            string AdditionalStubIncludes = "";
                            if (Action.CommandPath.GetFileName().Equals("cl.exe", StringComparison.OrdinalIgnoreCase))
                            {
                                string        ResponseFile    = Action.CommandArguments.Replace("\"", "").Replace("@", "").Trim();
                                StringBuilder WrapperContents = new StringBuilder();
                                using (StringWriter Writer = new StringWriter(WrapperContents))
                                {
                                    Writer.WriteLine("// PCH dependencies for {0}", ResponseFile);
                                    Writer.WriteLine("#if 0");
                                    foreach (FileItem Preqrequisite in Action.PrerequisiteItems)
                                    {
                                        if (Preqrequisite.AbsolutePath.EndsWith(".pch"))
                                        {
                                            Writer.WriteLine("#include \"{0}\"", Preqrequisite.AbsolutePath.Replace(".pch", ".obj"));
                                        }
                                    }
                                    Writer.WriteLine("#endif");
                                }

                                FileItem DummyResponseFileDependency = FileItem.CreateIntermediateTextFile(new FileReference(ResponseFile + ".dummy.h"), WrapperContents.ToString());
                                AdditionalStubIncludes = string.Format("/FI\"{0}\"", DummyResponseFileDependency);
                            }

                            // Add to script for execution by SN-DBS
                            string NewCommandArguments = "\"" + Action.CommandPath + "\"" + " " + AdditionalStubIncludes + " " + Action.CommandArguments;
                            ScriptFile.WriteLine(NewCommandArguments);
                            InActionThreadDictionary.Add(Action, DummyActionThread);
                            Action.StartTime = Action.EndTime = DateTimeOffset.Now;
                            Log.TraceInformation("[{0}/{1}] {2} {3}", JobNumber, InActions.Count, Action.CommandDescription, Action.StatusDescription);
                            JobNumber++;
                            NumScriptedActions++;
                            PrintDebugInfo |= Action.bPrintDebugInfo;

                            if (Action.DependencyListFile != null && File.Exists(Action.DependencyListFile.AbsolutePath))
                            {
                                Log.TraceVerbose("Deleting dependency list file {0}", Action.DependencyListFile.AbsolutePath);
                                File.Delete(Action.DependencyListFile.AbsolutePath);
                            }
                        }
                    }
                }
            }

            ScriptFile.Flush();
            ScriptFile.Close();
            ScriptFile.Dispose();
            ScriptFile = null;

            if (NumScriptedActions > 0)
            {
                // Create the process
                string             SCERoot                = Environment.GetEnvironmentVariable("SCE_ROOT_DIR");
                string             SNDBSExecutable        = Path.Combine(SCERoot, "Common/SN-DBS/bin/dbsbuild.exe");
                DirectoryReference TemplatesDir           = DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Programs", "UnrealBuildTool", "SndbsTemplates");
                string             IncludeRewriteRulesArg = String.Format("--include-rewrite-rules \"{0}\"", IncludeRewriteRulesFile.FullName);
                string             VerbosityLevel         = PrintDebugInfo ? "-v" : "-q";
                ProcessStartInfo   PSI = new ProcessStartInfo(SNDBSExecutable, String.Format("{0} -p UE4 -s \"{1}\" -templates \"{2}\" {3}", VerbosityLevel, FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "sndbs.bat").FullName, TemplatesDir.FullName, IncludeRewriteRulesArg));
                PSI.RedirectStandardOutput = true;
                PSI.RedirectStandardError  = true;
                PSI.UseShellExecute        = false;
                PSI.CreateNoWindow         = true;
                PSI.WorkingDirectory       = Path.GetFullPath(".");
                Process NewProcess = new Process();
                NewProcess.StartInfo           = PSI;
                NewProcess.OutputDataReceived += new DataReceivedEventHandler(ActionDebugOutput);
                NewProcess.ErrorDataReceived  += new DataReceivedEventHandler(ActionDebugOutput);
                DateTimeOffset StartTime = DateTimeOffset.Now;
                NewProcess.Start();
                NewProcess.BeginOutputReadLine();
                NewProcess.BeginErrorReadLine();

                NewProcess.WaitForExit();

                TimeSpan       Duration;
                DateTimeOffset EndTime = DateTimeOffset.Now;
                if (EndTime == DateTimeOffset.MinValue)
                {
                    Duration = DateTimeOffset.Now - StartTime;
                }
                else
                {
                    Duration = EndTime - StartTime;
                }

                DummyActionThread.bComplete = true;
                int ExitCode = NewProcess.ExitCode;
                if (ExitCode != 0)
                {
                    return(false);
                }
            }

            // Execute local tasks
            if (LocalActions.Count > 0)
            {
                return(ExecuteLocalActions(LocalActions, InActionThreadDictionary, InActions.Count));
            }

            return(true);
        }
Example #26
0
        /// <summary>
        /// Reads a config hierarchy (or retrieve it from the cache)
        /// </summary>
        /// <param name="Type">The type of hierarchy to read</param>
        /// <param name="ProjectDir">The project directory to read the hierarchy for</param>
        /// <param name="Platform">Which platform to read platform-specific config files for</param>
        /// <param name="GeneratedConfigDir">Base directory for generated configs</param>
        /// <returns>The requested config hierarchy</returns>
        public static ConfigHierarchy ReadHierarchy(ConfigHierarchyType Type, DirectoryReference ProjectDir, UnrealTargetPlatform Platform, DirectoryReference GeneratedConfigDir = null)
        {
            // Get the key to use for the cache. It cannot be null, so we use the engine directory if a project directory is not given.
            ConfigHierarchyKey Key = new ConfigHierarchyKey(Type, ProjectDir, Platform);

            // Try to get the cached hierarchy with this key
            ConfigHierarchy Hierarchy;

            lock (HierarchyKeyToHierarchy)
            {
                if (!HierarchyKeyToHierarchy.TryGetValue(Key, out Hierarchy))
                {
                    List <ConfigFile> Files = new List <ConfigFile>();
                    foreach (FileReference IniFileName in ConfigHierarchy.EnumerateConfigFileLocations(Type, ProjectDir, Platform))
                    {
                        ConfigFile File;
                        if (TryReadFile(IniFileName, out File))
                        {
                            Files.Add(File);
                        }
                    }

                    // If we haven't been given a generated project dir, but we do have a project then the generated configs
                    // should go into ProjectDir/Saved
                    if (GeneratedConfigDir == null && ProjectDir != null)
                    {
                        GeneratedConfigDir = DirectoryReference.Combine(ProjectDir, "Saved");
                    }

                    if (GeneratedConfigDir != null)
                    {
                        // We know where the generated version of this config file lives, so we can read it back in
                        // and include any user settings from there in our hierarchy
                        string        BaseIniName            = Enum.GetName(typeof(ConfigHierarchyType), Type);
                        string        PlatformName           = ConfigHierarchy.GetIniPlatformName(Platform);
                        FileReference DestinationIniFilename = FileReference.Combine(GeneratedConfigDir, "Config", PlatformName, BaseIniName + ".ini");
                        ConfigFile    File;
                        if (TryReadFile(DestinationIniFilename, out File))
                        {
                            Files.Add(File);
                        }
                    }

                    // Handle command line overrides
                    string[] CmdLine            = Environment.GetCommandLineArgs();
                    string   IniConfigArgPrefix = "-ini:" + Enum.GetName(typeof(ConfigHierarchyType), Type) + ":";
                    foreach (string CmdLineArg in CmdLine)
                    {
                        if (CmdLineArg.StartsWith(IniConfigArgPrefix))
                        {
                            ConfigFile OverrideFile = new ConfigFile(CmdLineArg.Substring(IniConfigArgPrefix.Length));
                            Files.Add(OverrideFile);
                        }
                    }

                    Hierarchy = new ConfigHierarchy(Files);
                    HierarchyKeyToHierarchy.Add(Key, Hierarchy);
                }
            }
            return(Hierarchy);
        }
 /// <summary>
 /// Helper function to get the console app BinaryName-Cmd.exe filename based on the binary filename.
 /// </summary>
 /// <param name="BinaryPath">Full path to the binary exe.</param>
 /// <returns></returns>
 public static FileReference GetAdditionalConsoleAppPath(FileReference BinaryPath)
 {
     return(FileReference.Combine(BinaryPath.Directory, BinaryPath.GetFileNameWithoutExtension() + "-Cmd" + BinaryPath.GetExtension()));
 }
Example #28
0
        /// <summary>
        /// Given a set of C++ files, generates another set of C++ files that #include all the original
        /// files, the goal being to compile the same code in fewer translation units.
        /// The "unity" files are written to the CompileEnvironment's OutputDirectory.
        /// </summary>
        /// <param name="Target">The target we're building</param>
        /// <param name="CPPFiles">The C++ files to #include.</param>
        /// <param name="CompileEnvironment">The environment that is used to compile the C++ files.</param>
        /// <param name="WorkingSet">Interface to query files which belong to the working set</param>
        /// <param name="BaseName">Base name to use for the Unity files</param>
        /// <param name="IntermediateDirectory">Intermediate directory for unity cpp files</param>
        /// <param name="Graph">The makefile being built</param>
        /// <param name="SourceFileToUnityFile">Receives a mapping of source file to unity file</param>
        /// <returns>The "unity" C++ files.</returns>
        public static List <FileItem> GenerateUnityCPPs(
            ReadOnlyTargetRules Target,
            List <FileItem> CPPFiles,
            CppCompileEnvironment CompileEnvironment,
            ISourceFileWorkingSet WorkingSet,
            string BaseName,
            DirectoryReference IntermediateDirectory,
            IActionGraphBuilder Graph,
            Dictionary <FileItem, FileItem> SourceFileToUnityFile
            )
        {
            List <FileItem> NewCPPFiles = new List <FileItem>();

            //UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(CompileEnvironment.Platform);

            // Figure out size of all input files combined. We use this to determine whether to use larger unity threshold or not.
            long TotalBytesInCPPFiles = CPPFiles.Sum(F => F.Length);

            // We have an increased threshold for unity file size if, and only if, all files fit into the same unity file. This
            // is beneficial when dealing with PCH files. The default PCH creation limit is X unity files so if we generate < X
            // this could be fairly slow and we'd rather bump the limit a bit to group them all into the same unity file.


            // When enabled, UnrealBuildTool will try to determine source files that you are actively iteratively changing, and break those files
            // out of their unity blobs so that you can compile them as individual translation units, much faster than recompiling the entire
            // unity blob each time.
            bool bUseAdaptiveUnityBuild = Target.bUseAdaptiveUnityBuild && !Target.bStressTestUnity;

            // Optimization only makes sense if PCH files are enabled.
            bool bForceIntoSingleUnityFile = Target.bStressTestUnity || (TotalBytesInCPPFiles < Target.NumIncludedBytesPerUnityCPP * 2 && Target.bUsePCHFiles);

            // Build the list of unity files.
            List <FileCollection> AllUnityFiles;
            {
                // Sort the incoming file paths alphabetically, so there will be consistency in unity blobs across multiple machines.
                // Note that we're relying on this not only sorting files within each directory, but also the directories
                // themselves, so the whole list of file paths is the same across computers.
                List <FileItem> SortedCPPFiles = CPPFiles.GetRange(0, CPPFiles.Count);
                {
                    // Case-insensitive file path compare, because you never know what is going on with local file systems
                    Comparison <FileItem> FileItemComparer = (FileA, FileB) => { return(FileA.AbsolutePath.ToLowerInvariant().CompareTo(FileB.AbsolutePath.ToLowerInvariant())); };
                    SortedCPPFiles.Sort(FileItemComparer);
                }


                // Figure out whether we REALLY want to use adaptive unity for this module.  If nearly every file in the module appears in the working
                // set, we'll just go ahead and let unity build do its thing.
                HashSet <FileItem> FilesInWorkingSet = new HashSet <FileItem>();
                if (bUseAdaptiveUnityBuild)
                {
                    int CandidateWorkingSetSourceFileCount = 0;
                    int WorkingSetSourceFileCount          = 0;
                    foreach (FileItem CPPFile in SortedCPPFiles)
                    {
                        ++CandidateWorkingSetSourceFileCount;

                        // Don't include writable source files into unity blobs
                        if (WorkingSet.Contains(CPPFile))
                        {
                            ++WorkingSetSourceFileCount;

                            // Mark this file as part of the working set.  This will be saved into the UBT Makefile so that
                            // the assembler can automatically invalidate the Makefile when the working set changes (allowing this
                            // code to run again, to build up new unity blobs.)
                            FilesInWorkingSet.Add(CPPFile);
                            Graph.AddFileToWorkingSet(CPPFile);
                        }
                    }

                    if (WorkingSetSourceFileCount >= CandidateWorkingSetSourceFileCount)
                    {
                        // Every single file in the module appears in the working set, so don't bother using adaptive unity for this
                        // module.  Otherwise it would make full builds really slow.
                        bUseAdaptiveUnityBuild = false;
                    }
                }

                UnityFileBuilder CPPUnityFileBuilder          = new UnityFileBuilder(bForceIntoSingleUnityFile ? -1 : Target.NumIncludedBytesPerUnityCPP);
                StringBuilder    AdaptiveUnityBuildInfoString = new StringBuilder();
                foreach (FileItem CPPFile in SortedCPPFiles)
                {
                    if (!bForceIntoSingleUnityFile && CPPFile.AbsolutePath.IndexOf(".GeneratedWrapper.", StringComparison.InvariantCultureIgnoreCase) != -1)
                    {
                        NewCPPFiles.Add(CPPFile);
                    }

                    // When adaptive unity is enabled, go ahead and exclude any source files that we're actively working with
                    if (bUseAdaptiveUnityBuild && FilesInWorkingSet.Contains(CPPFile))
                    {
                        // Just compile this file normally, not as part of the unity blob
                        NewCPPFiles.Add(CPPFile);

                        // Let the unity file builder know about the file, so that we can retain the existing size of the unity blobs.
                        // This won't actually make the source file part of the unity blob, but it will keep track of how big the
                        // file is so that other existing unity blobs from the same module won't be invalidated.  This prevents much
                        // longer compile times the first time you build after your working file set changes.
                        CPPUnityFileBuilder.AddVirtualFile(CPPFile);

                        string CPPFileName = Path.GetFileName(CPPFile.AbsolutePath);
                        if (AdaptiveUnityBuildInfoString.Length == 0)
                        {
                            AdaptiveUnityBuildInfoString.Append(String.Format("[Adaptive unity build] Excluded from {0} unity file: {1}", BaseName, CPPFileName));
                        }
                        else
                        {
                            AdaptiveUnityBuildInfoString.Append(", " + CPPFileName);
                        }
                    }
                    else
                    {
                        // If adaptive unity build is enabled for this module, add this source file to the set that will invalidate the makefile
                        if (bUseAdaptiveUnityBuild)
                        {
                            Graph.AddCandidateForWorkingSet(CPPFile);
                        }

                        // Compile this file as part of the unity blob
                        CPPUnityFileBuilder.AddFile(CPPFile);
                    }
                }

                if (AdaptiveUnityBuildInfoString.Length > 0)
                {
                    if (Target.bAdaptiveUnityCreatesDedicatedPCH)
                    {
                        Graph.AddDiagnostic("[Adaptive unity build] Creating dedicated PCH for each excluded file. Set bAdaptiveUnityCreatesDedicatedPCH to false in BuildConfiguration.xml to change this behavior.");
                    }
                    else if (Target.bAdaptiveUnityDisablesPCH)
                    {
                        Graph.AddDiagnostic("[Adaptive unity build] Disabling PCH for excluded files. Set bAdaptiveUnityDisablesPCH to false in BuildConfiguration.xml to change this behavior.");
                    }

                    if (Target.bAdaptiveUnityDisablesOptimizations)
                    {
                        Graph.AddDiagnostic("[Adaptive unity build] Disabling optimizations for excluded files. Set bAdaptiveUnityDisablesOptimizations to false in BuildConfiguration.xml to change this behavior.");
                    }
                    if (Target.bAdaptiveUnityEnablesEditAndContinue)
                    {
                        Graph.AddDiagnostic("[Adaptive unity build] Enabling Edit & Continue for excluded files. Set bAdaptiveUnityEnablesEditAndContinue to false in BuildConfiguration.xml to change this behavior.");
                    }

                    Graph.AddDiagnostic(AdaptiveUnityBuildInfoString.ToString());
                }

                AllUnityFiles = CPPUnityFileBuilder.GetUnityFiles();
            }

            // Create a set of CPP files that combine smaller CPP files into larger compilation units, along with the corresponding
            // actions to compile them.
            int CurrentUnityFileCount = 0;

            foreach (FileCollection UnityFile in AllUnityFiles)
            {
                ++CurrentUnityFileCount;

                StringWriter OutputUnityCPPWriter = new StringWriter();

                OutputUnityCPPWriter.WriteLine("// This file is automatically generated at compile-time to include some subset of the user-created cpp files.");

                // Add source files to the unity file
                foreach (FileItem CPPFile in UnityFile.Files)
                {
                    OutputUnityCPPWriter.WriteLine("#include \"{0}\"", CPPFile.AbsolutePath.Replace('\\', '/'));
                }

                // Determine unity file path name
                string UnityCPPFileName;
                if (AllUnityFiles.Count > 1)
                {
                    UnityCPPFileName = string.Format("{0}{1}.{2}_of_{3}.cpp", ModulePrefix, BaseName, CurrentUnityFileCount, AllUnityFiles.Count);
                }
                else
                {
                    UnityCPPFileName = string.Format("{0}{1}.cpp", ModulePrefix, BaseName);
                }
                FileReference UnityCPPFilePath = FileReference.Combine(IntermediateDirectory, UnityCPPFileName);

                // Write the unity file to the intermediate folder.
                FileItem UnityCPPFile = Graph.CreateIntermediateTextFile(UnityCPPFilePath, OutputUnityCPPWriter.ToString());
                NewCPPFiles.Add(UnityCPPFile);

                // Store the mapping of source files to unity files in the makefile
                foreach (FileItem SourceFile in UnityFile.Files)
                {
                    SourceFileToUnityFile[SourceFile] = UnityCPPFile;
                }
                foreach (FileItem SourceFile in UnityFile.VirtualFiles)
                {
                    SourceFileToUnityFile[SourceFile] = UnityCPPFile;
                }
            }

            return(NewCPPFiles);
        }
        /// <summary>
        /// Creates a rules assembly with the given parameters.
        /// </summary>
        /// <param name="ProjectFileName">The project file to create rules for. Null for the engine.</param>
        /// <param name="bUsePrecompiled">Whether to use a precompiled engine</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <returns>New rules assembly</returns>
        public static RulesAssembly CreateProjectRulesAssembly(FileReference ProjectFileName, bool bUsePrecompiled, bool bSkipCompile)
        {
            // Check if there's an existing assembly for this project
            RulesAssembly ProjectRulesAssembly;

            if (!LoadedAssemblyMap.TryGetValue(ProjectFileName, out ProjectRulesAssembly))
            {
                ProjectDescriptor Project = ProjectDescriptor.FromFile(ProjectFileName);

                // Create the parent assembly
                RulesAssembly Parent;
                if (Project.IsEnterpriseProject)
                {
                    Parent = CreateEnterpriseRulesAssembly(bUsePrecompiled, bSkipCompile);
                }
                else
                {
                    Parent = CreateEngineRulesAssembly(bUsePrecompiled, bSkipCompile);
                }

                DirectoryReference MainProjectDirectory = ProjectFileName.Directory;
                //DirectoryReference MainProjectSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Source");

                // Create a scope for things in this assembly
                RulesScope Scope = new RulesScope("Project", Parent.Scope);

                // Create a new context for modules created by this assembly
                ModuleRulesContext DefaultModuleContext = new ModuleRulesContext(Scope, MainProjectDirectory);
                DefaultModuleContext.bCanBuildDebugGame          = true;
                DefaultModuleContext.bCanHotReload               = true;
                DefaultModuleContext.bClassifyAsGameModuleForUHT = true;
                DefaultModuleContext.bCanUseForSharedPCH         = false;

                // gather modules from project and platforms
                Dictionary <FileReference, ModuleRulesContext> ModuleFiles = new Dictionary <FileReference, ModuleRulesContext>();
                List <FileReference> TargetFiles = new List <FileReference>();

                // Find all the project directories
                List <DirectoryReference> ProjectDirectories = new List <DirectoryReference>(UnrealBuildTool.GetAllProjectDirectories(ProjectFileName));
                if (Project.AdditionalRootDirectories != null)
                {
                    ProjectDirectories.AddRange(Project.AdditionalRootDirectories);
                }

                // Find all the rules/plugins under the project source directories
                foreach (DirectoryReference ProjectDirectory in ProjectDirectories)
                {
                    DirectoryReference ProjectSourceDirectory = DirectoryReference.Combine(ProjectDirectory, "Source");

                    AddModuleRulesWithContext(ProjectSourceDirectory, DefaultModuleContext, ModuleFiles);
                    TargetFiles.AddRange(FindAllRulesFiles(ProjectSourceDirectory, RulesFileType.Target));
                }

                // Find all the project plugins
                List <PluginInfo> ProjectPlugins = new List <PluginInfo>();
                ProjectPlugins.AddRange(Plugins.ReadProjectPlugins(MainProjectDirectory));

                // Add the project's additional plugin directories plugins too
                if (Project.AdditionalPluginDirectories != null)
                {
                    foreach (DirectoryReference AdditionalPluginDirectory in Project.AdditionalPluginDirectories)
                    {
                        ProjectPlugins.AddRange(Plugins.ReadAdditionalPlugins(AdditionalPluginDirectory));
                    }
                }

                // Find all the plugin module rules
                FindModuleRulesForPlugins(ProjectPlugins, DefaultModuleContext, ModuleFiles);

                // Add the games project's intermediate source folder
                DirectoryReference ProjectIntermediateSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Intermediate", "Source");
                if (DirectoryReference.Exists(ProjectIntermediateSourceDirectory))
                {
                    AddModuleRulesWithContext(ProjectIntermediateSourceDirectory, DefaultModuleContext, ModuleFiles);
                    TargetFiles.AddRange(FindAllRulesFiles(ProjectIntermediateSourceDirectory, RulesFileType.Target));
                }

                // Compile the assembly. If there are no module or target files, just use the parent assembly.
                FileReference AssemblyFileName = FileReference.Combine(MainProjectDirectory, "Intermediate", "Build", "BuildRules", ProjectFileName.GetFileNameWithoutExtension() + "ModuleRules" + FrameworkAssemblyExtension);
                if (ModuleFiles.Count == 0 && TargetFiles.Count == 0)
                {
                    ProjectRulesAssembly = Parent;
                }
                else
                {
                    ProjectRulesAssembly = new RulesAssembly(Scope, new List <DirectoryReference> {
                        MainProjectDirectory
                    }, ProjectPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: null, bReadOnly: UnrealBuildTool.IsProjectInstalled(), bSkipCompile: bSkipCompile, Parent: Parent);
                }
                LoadedAssemblyMap.Add(ProjectFileName, ProjectRulesAssembly);
            }
            return(ProjectRulesAssembly);
        }
Example #30
0
 /// <summary>
 /// Find the location of the XML config schema
 /// </summary>
 /// <returns>The location of the schema file</returns>
 public static FileReference GetSchemaLocation()
 {
     return(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Saved", "UnrealBuildTool", "BuildConfiguration.Schema.xsd"));
 }