Ejemplo n.º 1
0
        /// <summary>
        /// Get host compiler path for ISPC.
        /// </summary>
        /// <param name="Platform">Which OS build platform is running on.</param>
        /// <returns>Path to ISPC compiler</returns>
        public virtual string GetISPCHostCompilerPath(UnrealTargetPlatform Platform)
        {
            string ISPCCompilerPathCommon = Path.Combine(UnrealBuildTool.EngineSourceDirectory.FullName, "ThirdParty", "Intel", "ISPC", "bin");
            string ISPCArchitecturePath   = "";
            string ExeExtension           = ".exe";

            if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Windows))
            {
                ISPCArchitecturePath = "Windows";
            }
            else if (Platform == UnrealTargetPlatform.Linux)
            {
                ISPCArchitecturePath = "Linux";
                ExeExtension         = "";
            }
            else if (Platform == UnrealTargetPlatform.Mac)
            {
                ISPCArchitecturePath = "Mac";
                ExeExtension         = "";
            }
            else
            {
                Log.TraceWarning("Unsupported ISPC host!");
            }

            return(Path.Combine(ISPCCompilerPathCommon, ISPCArchitecturePath, "ispc" + ExeExtension));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Get OS target for ISPC.
        /// </summary>
        /// <param name="Platform">Which OS platform to target.</param>
        /// <returns>OS string passed to ISPC compiler</returns>
        public virtual string GetISPCOSTarget(UnrealTargetPlatform Platform)
        {
            string ISPCOS = "";

            if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Windows))
            {
                ISPCOS += "windows";
            }
            else if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Unix))
            {
                ISPCOS += "linux";
            }
            else if (Platform == UnrealTargetPlatform.Android || Platform == UnrealTargetPlatform.Lumin)
            {
                ISPCOS += "android";
            }
            else if (Platform == UnrealTargetPlatform.Mac)
            {
                ISPCOS += "macos";
            }
            else
            {
                Log.TraceWarning("Unsupported ISPC platform target!");
            }

            return(ISPCOS);
        }
        /// <summary>
        /// Write C++ toolchain information to JSON writer
        /// </summary>
        /// <param name="Target"></param>
        /// <param name="Writer"></param>
        private static void ExportEnvironmentToJson(UEBuildTarget Target, JsonWriter Writer)
        {
            CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();

            Writer.WriteArrayStart("EnvironmentIncludePaths");
            foreach (DirectoryReference Path in GlobalCompileEnvironment.UserIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }
            foreach (DirectoryReference Path in GlobalCompileEnvironment.SystemIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }

            // TODO: get corresponding includes for specific platforms
            if (UEBuildPlatform.IsPlatformInGroup(Target.Platform, UnrealPlatformGroup.Windows))
            {
                foreach (DirectoryReference Path in Target.Rules.WindowsPlatform.Environment.IncludePaths)
                {
                    Writer.WriteValue(Path.FullName);
                }
            }
            Writer.WriteArrayEnd();

            Writer.WriteArrayStart("EnvironmentDefinitions");
            foreach (string Definition in GlobalCompileEnvironment.Definitions)
            {
                Writer.WriteValue(Definition);
            }
            Writer.WriteArrayEnd();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Write C++ toolchain information to JSON writer
        /// </summary>
        /// <param name="Target"></param>
        /// <param name="Writer"></param>
        private void ExportEnvironmentToJson(UEBuildTarget Target, JsonWriter Writer)
        {
            CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();

            RootToolchainInfo = GenerateToolchainInfo(GlobalCompileEnvironment);

            Writer.WriteObjectStart("ToolchainInfo");
            foreach (Tuple <string, object> Field in RootToolchainInfo.GetFields())
            {
                WriteField(Target.TargetName, Writer, Field);
            }
            Writer.WriteObjectEnd();

            Writer.WriteArrayStart("EnvironmentIncludePaths");
            foreach (DirectoryReference Path in GlobalCompileEnvironment.UserIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }
            foreach (DirectoryReference Path in GlobalCompileEnvironment.SystemIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }

            if (UEBuildPlatform.IsPlatformInGroup(Target.Platform, UnrealPlatformGroup.Windows))
            {
                foreach (DirectoryReference Path in Target.Rules.WindowsPlatform.Environment.IncludePaths)
                {
                    Writer.WriteValue(Path.FullName);
                }
            }
            else if (UEBuildPlatform.IsPlatformInGroup(Target.Platform, UnrealPlatformGroup.Apple) &&
                     UEBuildPlatform.IsPlatformInGroup(BuildHostPlatform.Current.Platform, UnrealPlatformGroup.Apple))
            {
                // Only generate Apple system include paths when host platform is Apple OS
                // TODO: Fix case when working with MacOS on Windows host platform
                foreach (string Path in AppleHelper.GetAppleSystemIncludePaths(GlobalCompileEnvironment.Architecture, Target.Platform))
                {
                    Writer.WriteValue(Path);
                }
            }
            // TODO: get corresponding includes for Linux

            Writer.WriteArrayEnd();

            Writer.WriteArrayStart("EnvironmentDefinitions");
            foreach (string Definition in GlobalCompileEnvironment.Definitions)
            {
                Writer.WriteValue(Definition);
            }
            Writer.WriteArrayEnd();
        }
Ejemplo n.º 5
0
            public IList <string> GetAppleSystemIncludePaths(string Architecture, UnrealTargetPlatform Platform)
            {
                if (!UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Apple))
                {
                    throw new InvalidOperationException("xcrun can be run only for Apple's platforms");
                }

                string SDKPath = GetSDKPath(Architecture, Platform);

                if (!CachedIncludePaths.ContainsKey(SDKPath))
                {
                    CalculateSystemIncludePaths(SDKPath);
                }

                return(CachedIncludePaths[SDKPath]);
            }
Ejemplo n.º 6
0
        /// <summary>
        /// Get CPU architecture target for ISPC.
        /// </summary>
        /// <param name="Platform">Which OS platform to target.</param>
        /// <param name="Arch">Which architecture inside an OS platform to target. Only used for Android currently.</param>
        /// <returns>Arch string passed to ISPC compiler</returns>
        public virtual string GetISPCArchTarget(UnrealTargetPlatform Platform, string Arch)
        {
            string ISPCArch = "";

            if ((UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Windows) && Platform != UnrealTargetPlatform.Win32) ||
                (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Unix) && Platform != UnrealTargetPlatform.LinuxAArch64) ||
                Platform == UnrealTargetPlatform.Mac)
            {
                ISPCArch += "x86-64";
            }
            else if (Platform == UnrealTargetPlatform.Win32)
            {
                ISPCArch += "x86";
            }
            else if (Platform == UnrealTargetPlatform.LinuxAArch64)
            {
                ISPCArch += "aarch64";
            }
            else if (Platform == UnrealTargetPlatform.Android || Platform == UnrealTargetPlatform.Lumin)
            {
                switch (Arch)
                {
                case "-armv7": ISPCArch += "arm"; break;                         // Assumes NEON is in use

                case "-arm64": ISPCArch += "aarch64"; break;

                case "-x86": ISPCArch += "x86"; break;

                case "-x64": ISPCArch += "x86-64"; break;

                default: Log.TraceWarning("Invalid Android architecture for ISPC. At least one architecture (armv7, x86, etc) needs to be selected in the project settings to build"); break;
                }
            }
            else
            {
                Log.TraceWarning("Unsupported ISPC platform target!");
            }

            return(ISPCArch);
        }
        /// <summary>
        /// Write C++ toolchain information to JSON writer
        /// </summary>
        /// <param name="Target"></param>
        /// <param name="Writer"></param>
        private void ExportEnvironmentToJson(UEBuildTarget Target, JsonWriter Writer)
        {
            CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();

            RootToolchainInfo = GenerateToolchainInfo(GlobalCompileEnvironment);

            Writer.WriteObjectStart("ToolchainInfo");
            foreach (Tuple <string, object> Field in RootToolchainInfo.GetFields())
            {
                WriteField(Target.TargetName, Writer, Field);
            }
            Writer.WriteObjectEnd();

            Writer.WriteArrayStart("EnvironmentIncludePaths");
            foreach (DirectoryReference Path in GlobalCompileEnvironment.UserIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }
            foreach (DirectoryReference Path in GlobalCompileEnvironment.SystemIncludePaths)
            {
                Writer.WriteValue(Path.FullName);
            }

            // TODO: get corresponding includes for specific platforms
            if (UEBuildPlatform.IsPlatformInGroup(Target.Platform, UnrealPlatformGroup.Windows))
            {
                foreach (DirectoryReference Path in Target.Rules.WindowsPlatform.Environment.IncludePaths)
                {
                    Writer.WriteValue(Path.FullName);
                }
            }
            Writer.WriteArrayEnd();

            Writer.WriteArrayStart("EnvironmentDefinitions");
            foreach (string Definition in GlobalCompileEnvironment.Definitions)
            {
                Writer.WriteValue(Definition);
            }
            Writer.WriteArrayEnd();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Get object file suffix for ISPC.
        /// </summary>
        /// <param name="Platform">Which OS build platform is running on.</param>
        /// <returns>Object file suffix</returns>
        public virtual string GetISPCObjectFileSuffix(UnrealTargetPlatform Platform)
        {
            string Suffix = "";

            if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Windows))
            {
                Suffix += ".obj";
            }
            else if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Unix) ||
                     Platform == UnrealTargetPlatform.Mac ||
                     Platform == UnrealTargetPlatform.Android ||
                     Platform == UnrealTargetPlatform.Lumin)
            {
                Suffix += ".o";
            }
            else
            {
                Log.TraceWarning("Unsupported ISPC platform target!");
            }

            return(Suffix);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Get CPU Instruction set targets for ISPC.
        /// </summary>
        /// <param name="Platform">Which OS platform to target.</param>
        /// <param name="Arch">Which architecture inside an OS platform to target. Only used for Android currently.</param>
        /// <returns>List of instruction set targets passed to ISPC compiler</returns>
        public virtual List <string> GetISPCCompileTargets(UnrealTargetPlatform Platform, string Arch)
        {
            List <string> ISPCTargets = new List <string>();

            if (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Windows) ||
                (UEBuildPlatform.IsPlatformInGroup(Platform, UnrealPlatformGroup.Unix) && Platform != UnrealTargetPlatform.LinuxAArch64) ||
                Platform == UnrealTargetPlatform.Mac)
            {
                ISPCTargets.AddRange(new string[] { "avx512skx-i32x8", "avx2", "avx", "sse4", "sse2" });
            }
            else if (Platform == UnrealTargetPlatform.LinuxAArch64)
            {
                ISPCTargets.AddRange(new string[] { "neon" });
            }
            else if (Platform == UnrealTargetPlatform.Android || Platform == UnrealTargetPlatform.Lumin)
            {
                switch (Arch)
                {
                case "-armv7": ISPCTargets.Add("neon"); break;                         // Assumes NEON is in use

                case "-arm64": ISPCTargets.Add("neon"); break;

                case "-x86": ISPCTargets.AddRange(new string[] { "sse4", "sse2" }); break;

                case "-x64": ISPCTargets.AddRange(new string[] { "sse4", "sse2" }); break;

                default: Log.TraceWarning("Invalid Android architecture for ISPC. At least one architecture (armv7, x86, etc) needs to be selected in the project settings to build"); break;
                }
            }
            else
            {
                Log.TraceWarning("Unsupported ISPC platform target!");
            }

            return(ISPCTargets);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Patch the action graph for hot reloading, mapping files according to the given dictionary.
        /// </summary>
        public static void PatchActionGraph(IEnumerable <Action> Actions, Dictionary <FileReference, FileReference> OriginalFileToHotReloadFile)
        {
            // Gather all of the response files for link actions.  We're going to need to patch 'em up after we figure out new
            // names for all of the output files and import libraries
            List <string> ResponseFilePaths = new List <string>();

            // Same as Response files but for all of the link.sh files for link actions.
            // Only used on BuildHostPlatform Linux
            List <string> LinkScriptFilePaths = new List <string>();

            // Keep a map of the original file names and their new file names, so we can fix up response files after
            Dictionary <string, string> OriginalFileNameAndNewFileNameList_NoExtensions = new Dictionary <string, string>();

            // Finally, we'll keep track of any file items that we had to create counterparts for change file names, so we can fix those up too
            Dictionary <FileItem, FileItem> AffectedOriginalFileItemAndNewFileItemMap = new Dictionary <FileItem, FileItem>();

            foreach (Action Action in Actions.Where((Action) => Action.ActionType == ActionType.Link))
            {
                // Assume that the first produced item (with no extension) is our output file name
                FileReference HotReloadFile;
                if (!OriginalFileToHotReloadFile.TryGetValue(Action.ProducedItems[0].Location, out HotReloadFile))
                {
                    continue;
                }

                string OriginalFileNameWithoutExtension = Utils.GetFilenameWithoutAnyExtensions(Action.ProducedItems[0].AbsolutePath);
                string NewFileNameWithoutExtension      = Utils.GetFilenameWithoutAnyExtensions(HotReloadFile.FullName);

                // Find the response file in the command line.  We'll need to make a copy of it with our new file name.
                string ResponseFileExtension  = ".response";
                int    ResponseExtensionIndex = Action.CommandArguments.IndexOf(ResponseFileExtension, StringComparison.InvariantCultureIgnoreCase);
                if (ResponseExtensionIndex != -1)
                {
                    int ResponseFilePathIndex = Action.CommandArguments.LastIndexOf("@\"", ResponseExtensionIndex);
                    if (ResponseFilePathIndex == -1)
                    {
                        throw new BuildException("Couldn't find response file path in action's command arguments when hot reloading");
                    }

                    string OriginalResponseFilePathWithoutExtension = Action.CommandArguments.Substring(ResponseFilePathIndex + 2, (ResponseExtensionIndex - ResponseFilePathIndex) - 2);
                    string OriginalResponseFilePath = OriginalResponseFilePathWithoutExtension + ResponseFileExtension;

                    string NewResponseFilePath = ReplaceBaseFileName(OriginalResponseFilePath, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);

                    // Copy the old response file to the new path
                    if (String.Compare(OriginalResponseFilePath, NewResponseFilePath, StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        File.Copy(OriginalResponseFilePath, NewResponseFilePath, overwrite: true);
                    }

                    // Keep track of the new response file name.  We'll have to do some edits afterwards.
                    ResponseFilePaths.Add(NewResponseFilePath);
                }

                // Find the *.link.sh file in the command line.  We'll need to make a copy of it with our new file name.
                // Only currently used on Linux
                if (UEBuildPlatform.IsPlatformInGroup(BuildHostPlatform.Current.Platform, UnrealPlatformGroup.Unix))
                {
                    string LinkScriptFileExtension  = ".link.sh";
                    int    LinkScriptExtensionIndex = Action.CommandArguments.IndexOf(LinkScriptFileExtension, StringComparison.InvariantCultureIgnoreCase);
                    if (LinkScriptExtensionIndex != -1)
                    {
                        // We expect the script invocation to be quoted
                        int LinkScriptFilePathIndex = Action.CommandArguments.LastIndexOf("\"", LinkScriptExtensionIndex);
                        if (LinkScriptFilePathIndex == -1)
                        {
                            throw new BuildException("Couldn't find link script file path in action's command arguments when hot reloading. Is the path quoted?");
                        }

                        string OriginalLinkScriptFilePathWithoutExtension = Action.CommandArguments.Substring(LinkScriptFilePathIndex + 1, (LinkScriptExtensionIndex - LinkScriptFilePathIndex) - 1);
                        string OriginalLinkScriptFilePath = OriginalLinkScriptFilePathWithoutExtension + LinkScriptFileExtension;

                        string NewLinkScriptFilePath = ReplaceBaseFileName(OriginalLinkScriptFilePath, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);

                        // Copy the old response file to the new path
                        File.Copy(OriginalLinkScriptFilePath, NewLinkScriptFilePath, overwrite: true);

                        // Keep track of the new response file name.  We'll have to do some edits afterwards.
                        LinkScriptFilePaths.Add(NewLinkScriptFilePath);
                    }

                    // Update this action's list of prerequisite items too
                    for (int ItemIndex = 0; ItemIndex < Action.PrerequisiteItems.Count; ++ItemIndex)
                    {
                        FileItem OriginalPrerequisiteItem    = Action.PrerequisiteItems[ItemIndex];
                        string   NewPrerequisiteItemFilePath = ReplaceBaseFileName(OriginalPrerequisiteItem.AbsolutePath, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);

                        if (OriginalPrerequisiteItem.AbsolutePath != NewPrerequisiteItemFilePath)
                        {
                            // OK, the prerequisite item's file name changed so we'll update it to point to our new file
                            FileItem NewPrerequisiteItem = FileItem.GetItemByPath(NewPrerequisiteItemFilePath);
                            Action.PrerequisiteItems[ItemIndex] = NewPrerequisiteItem;

                            // Keep track of it so we can fix up dependencies in a second pass afterwards
                            AffectedOriginalFileItemAndNewFileItemMap.Add(OriginalPrerequisiteItem, NewPrerequisiteItem);

                            ResponseExtensionIndex = OriginalPrerequisiteItem.AbsolutePath.IndexOf(ResponseFileExtension, StringComparison.InvariantCultureIgnoreCase);
                            if (ResponseExtensionIndex != -1)
                            {
                                string OriginalResponseFilePathWithoutExtension = OriginalPrerequisiteItem.AbsolutePath.Substring(0, ResponseExtensionIndex);
                                string OriginalResponseFilePath = OriginalResponseFilePathWithoutExtension + ResponseFileExtension;

                                string NewResponseFilePath = ReplaceBaseFileName(OriginalResponseFilePath, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);

                                // Copy the old response file to the new path
                                File.Copy(OriginalResponseFilePath, NewResponseFilePath, overwrite: true);

                                // Keep track of the new response file name.  We'll have to do some edits afterwards.
                                ResponseFilePaths.Add(NewResponseFilePath);
                            }
                        }
                    }
                }

                // Update this action's list of produced items too
                for (int ItemIndex = 0; ItemIndex < Action.ProducedItems.Count; ++ItemIndex)
                {
                    FileItem OriginalProducedItem = Action.ProducedItems[ItemIndex];

                    string NewProducedItemFilePath = ReplaceBaseFileName(OriginalProducedItem.AbsolutePath, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);
                    if (OriginalProducedItem.AbsolutePath != NewProducedItemFilePath)
                    {
                        // OK, the produced item's file name changed so we'll update it to point to our new file
                        FileItem NewProducedItem = FileItem.GetItemByPath(NewProducedItemFilePath);
                        Action.ProducedItems[ItemIndex] = NewProducedItem;

                        // Keep track of it so we can fix up dependencies in a second pass afterwards
                        AffectedOriginalFileItemAndNewFileItemMap.Add(OriginalProducedItem, NewProducedItem);
                    }
                }

                // Fix up the list of items to delete too
                for (int Idx = 0; Idx < Action.DeleteItems.Count; Idx++)
                {
                    FileItem NewItem;
                    if (AffectedOriginalFileItemAndNewFileItemMap.TryGetValue(Action.DeleteItems[Idx], out NewItem))
                    {
                        Action.DeleteItems[Idx] = NewItem;
                    }
                }

                // The status description of the item has the file name, so we'll update it too
                Action.StatusDescription = ReplaceBaseFileName(Action.StatusDescription, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);

                // Keep track of the file names, so we can fix up response files afterwards.
                if (!OriginalFileNameAndNewFileNameList_NoExtensions.ContainsKey(OriginalFileNameWithoutExtension))
                {
                    OriginalFileNameAndNewFileNameList_NoExtensions[OriginalFileNameWithoutExtension] = NewFileNameWithoutExtension;
                }
                else if (OriginalFileNameAndNewFileNameList_NoExtensions[OriginalFileNameWithoutExtension] != NewFileNameWithoutExtension)
                {
                    throw new BuildException("Unexpected conflict in renaming files; {0} maps to {1} and {2}", OriginalFileNameWithoutExtension, OriginalFileNameAndNewFileNameList_NoExtensions[OriginalFileNameWithoutExtension], NewFileNameWithoutExtension);
                }
            }


            // Do another pass and update any actions that depended on the original file names that we changed
            foreach (Action Action in Actions)
            {
                for (int ItemIndex = 0; ItemIndex < Action.PrerequisiteItems.Count; ++ItemIndex)
                {
                    FileItem OriginalFileItem = Action.PrerequisiteItems[ItemIndex];

                    FileItem NewFileItem;
                    if (AffectedOriginalFileItemAndNewFileItemMap.TryGetValue(OriginalFileItem, out NewFileItem))
                    {
                        // OK, looks like we need to replace this file item because we've renamed the file
                        Action.PrerequisiteItems[ItemIndex] = NewFileItem;
                    }
                }
            }


            if (OriginalFileNameAndNewFileNameList_NoExtensions.Count > 0)
            {
                // Update all the paths in link actions
                foreach (Action Action in Actions.Where((Action) => Action.ActionType == ActionType.Link))
                {
                    foreach (KeyValuePair <string, string> FileNameTuple in OriginalFileNameAndNewFileNameList_NoExtensions)
                    {
                        string OriginalFileNameWithoutExtension = FileNameTuple.Key;
                        string NewFileNameWithoutExtension      = FileNameTuple.Value;

                        Action.CommandArguments = ReplaceBaseFileName(Action.CommandArguments, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);
                    }
                }

                foreach (string ResponseFilePath in ResponseFilePaths)
                {
                    // Load the file up
                    string FileContents = Utils.ReadAllText(ResponseFilePath);

                    // Replace all of the old file names with new ones
                    foreach (KeyValuePair <string, string> FileNameTuple in OriginalFileNameAndNewFileNameList_NoExtensions)
                    {
                        string OriginalFileNameWithoutExtension = FileNameTuple.Key;
                        string NewFileNameWithoutExtension      = FileNameTuple.Value;

                        FileContents = ReplaceBaseFileName(FileContents, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);
                    }

                    // Overwrite the original file
                    File.WriteAllText(ResponseFilePath, FileContents, new System.Text.UTF8Encoding(false));
                }

                if (UEBuildPlatform.IsPlatformInGroup(BuildHostPlatform.Current.Platform, UnrealPlatformGroup.Unix))
                {
                    foreach (string LinkScriptFilePath in LinkScriptFilePaths)
                    {
                        // Load the file up
                        string FileContents = Utils.ReadAllText(LinkScriptFilePath);

                        // Replace all of the old file names with new ones
                        foreach (KeyValuePair <string, string> FileNameTuple in OriginalFileNameAndNewFileNameList_NoExtensions)
                        {
                            string OriginalFileNameWithoutExtension = FileNameTuple.Key;
                            string NewFileNameWithoutExtension      = FileNameTuple.Value;

                            FileContents = ReplaceBaseFileName(FileContents, OriginalFileNameWithoutExtension, NewFileNameWithoutExtension);
                        }

                        // Overwrite the original file
                        File.WriteAllText(LinkScriptFilePath, FileContents, new System.Text.UTF8Encoding(false));
                    }
                }
            }

            // Update the action that writes out the module manifests
            foreach (Action Action in Actions)
            {
                if (Action.ActionType == ActionType.WriteMetadata)
                {
                    string Arguments = Action.CommandArguments;

                    // Find the argument for the metadata file
                    const string InputArgument = "-Input=";

                    int InputIdx = Arguments.IndexOf(InputArgument);
                    if (InputIdx == -1)
                    {
                        throw new Exception("Missing -Input= argument to WriteMetadata command when patching action graph.");
                    }

                    int FileNameIdx = InputIdx + InputArgument.Length;
                    if (Arguments[FileNameIdx] == '\"')
                    {
                        FileNameIdx++;
                    }

                    int FileNameEndIdx = FileNameIdx;
                    while (FileNameEndIdx < Arguments.Length && (Arguments[FileNameEndIdx] != ' ' || Arguments[FileNameIdx - 1] == '\"') && Arguments[FileNameEndIdx] != '\"')
                    {
                        FileNameEndIdx++;
                    }

                    // Read the metadata file
                    FileReference TargetInfoFile = new FileReference(Arguments.Substring(FileNameIdx, FileNameEndIdx - FileNameIdx));
                    if (!FileReference.Exists(TargetInfoFile))
                    {
                        throw new Exception(String.Format("Unable to find metadata file to patch action graph ({0})", TargetInfoFile));
                    }

                    // Update the module names
                    WriteMetadataTargetInfo TargetInfo = BinaryFormatterUtils.Load <WriteMetadataTargetInfo>(TargetInfoFile);
                    foreach (KeyValuePair <FileReference, ModuleManifest> FileNameToVersionManifest in TargetInfo.FileToManifest)
                    {
                        KeyValuePair <string, string>[] ManifestEntries = FileNameToVersionManifest.Value.ModuleNameToFileName.ToArray();
                        foreach (KeyValuePair <string, string> Manifest in ManifestEntries)
                        {
                            FileReference OriginalFile = FileReference.Combine(FileNameToVersionManifest.Key.Directory, Manifest.Value);

                            FileReference HotReloadFile;
                            if (OriginalFileToHotReloadFile.TryGetValue(OriginalFile, out HotReloadFile))
                            {
                                FileNameToVersionManifest.Value.ModuleNameToFileName[Manifest.Key] = HotReloadFile.GetFileName();
                            }
                        }
                    }

                    // Write the hot-reload metadata file and update the argument list
                    FileReference HotReloadTargetInfoFile = FileReference.Combine(TargetInfoFile.Directory, "Metadata-HotReload.dat");
                    BinaryFormatterUtils.SaveIfDifferent(HotReloadTargetInfoFile, TargetInfo);

                    Action.PrerequisiteItems.RemoveAll(x => x.Location == TargetInfoFile);
                    Action.PrerequisiteItems.Add(FileItem.GetItemByFileReference(HotReloadTargetInfoFile));

                    Action.CommandArguments = Arguments.Substring(0, FileNameIdx) + HotReloadTargetInfoFile + Arguments.Substring(FileNameEndIdx);
                }
            }
        }
Ejemplo n.º 11
0
        public override CPPOutput CompileISPCFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
        {
            CPPOutput Result = new CPPOutput();

            if (!CompileEnvironment.bCompileISPC)
            {
                return(Result);
            }

            List <string> CompileTargets = GetISPCCompileTargets(CompileEnvironment.Platform, null);

            foreach (FileItem ISPCFile in InputFiles)
            {
                Action CompileAction = Graph.CreateAction(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";
                CompileAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory;
                CompileAction.CommandPath        = new FileReference(GetISPCHostCompilerPath(BuildHostPlatform.Current.Platform));
                CompileAction.StatusDescription  = Path.GetFileName(ISPCFile.AbsolutePath);

                // Disable remote execution to workaround mismatched case on XGE
                CompileAction.bCanExecuteRemotely = false;

                List <string> Arguments = new List <string>();

                // Add the ISPC file to be compiled.
                Arguments.Add(String.Format(" \"{0}\"", ISPCFile.AbsolutePath));

                List <FileItem> CompiledISPCObjFiles = new List <FileItem>();
                string          TargetString         = "";

                foreach (string Target in CompileTargets)
                {
                    string ObjTarget = Target;

                    if (Target.Contains("-"))
                    {
                        // Remove lane width and gang size from obj file name
                        ObjTarget = Target.Split('-')[0];
                    }

                    FileItem CompiledISPCObjFile;

                    if (CompileTargets.Count > 1)
                    {
                        CompiledISPCObjFile = FileItem.GetItemByFileReference(
                            FileReference.Combine(
                                OutputDir,
                                Path.GetFileName(ISPCFile.AbsolutePath) + "_" + ObjTarget + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                                )
                            );
                    }
                    else
                    {
                        CompiledISPCObjFile = FileItem.GetItemByFileReference(
                            FileReference.Combine(
                                OutputDir,
                                Path.GetFileName(ISPCFile.AbsolutePath) + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                                )
                            );
                    }

                    // Add the ISA specific ISPC obj files to the produced item list.
                    CompiledISPCObjFiles.Add(CompiledISPCObjFile);

                    // Build target string. No comma on last
                    if (Target == CompileTargets[CompileTargets.Count - 1])                   // .Last()
                    {
                        TargetString += Target;
                    }
                    else
                    {
                        TargetString += Target + ",";
                    }
                }

                // Add the common ISPC obj file to the produced item list.
                FileItem CompiledISPCObjFileNoISA = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                        )
                    );

                CompiledISPCObjFiles.Add(CompiledISPCObjFileNoISA);

                // Add the output ISPC obj file
                Arguments.Add(String.Format("-o \"{0}\"", CompiledISPCObjFileNoISA));

                // Build target triplet
                Arguments.Add(String.Format("--target-os=\"{0}\"", GetISPCOSTarget(CompileEnvironment.Platform)));
                Arguments.Add(String.Format("--arch=\"{0}\"", GetISPCArchTarget(CompileEnvironment.Platform, null)));
                Arguments.Add(String.Format("--target=\"{0}\"", TargetString));

                if (CompileEnvironment.Configuration == CppConfiguration.Debug)
                {
                    Arguments.Add("-g -O0");
                }
                else
                {
                    Arguments.Add("-O2");
                }

                // PIC is needed for modular builds except on Windows
                if ((CompileEnvironment.bIsBuildingDLL ||
                     CompileEnvironment.bIsBuildingLibrary) &&
                    !UEBuildPlatform.IsPlatformInGroup(CompileEnvironment.Platform, UnrealPlatformGroup.Windows))
                {
                    Arguments.Add("--pic");
                }

                // Include paths. Don't use AddIncludePath() here, since it uses the full path and exceeds the max command line length.
                foreach (DirectoryReference IncludePath in CompileEnvironment.UserIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", IncludePath));
                }

                // System include paths.
                foreach (DirectoryReference SystemIncludePath in CompileEnvironment.SystemIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", SystemIncludePath));
                }

                // Preprocessor definitions.
                foreach (string Definition in CompileEnvironment.Definitions)
                {
                    Arguments.Add(String.Format("-D\"{0}\"", Definition));
                }

                // Consume the included header dependency list
                if (CompileEnvironment.bGenerateDependenciesFile)
                {
                    FileItem DependencyListFile = FileItem.GetItemByFileReference(FileReference.Combine(OutputDir, Path.GetFileName(ISPCFile.AbsolutePath) + ".txt"));
                    CompileAction.DependencyListFile = DependencyListFile;
                    CompileAction.PrerequisiteItems.Add(DependencyListFile);
                }

                CompileAction.ProducedItems.AddRange(CompiledISPCObjFiles);
                Result.ObjectFiles.AddRange(CompiledISPCObjFiles);

                FileReference ResponseFileName = new FileReference(CompiledISPCObjFileNoISA.AbsolutePath + ".response");
                FileItem      ResponseFileItem = Graph.CreateIntermediateTextFile(ResponseFileName, Arguments.Select(x => Utils.ExpandVariables(x)));
                CompileAction.CommandArguments = " @\"" + ResponseFileName + "\"";
                CompileAction.PrerequisiteItems.Add(ResponseFileItem);

                // Add the source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(ISPCFile);

                Log.TraceVerbose("   ISPC Compiling " + CompileAction.StatusDescription + ": \"" + CompileAction.CommandPath + "\"" + CompileAction.CommandArguments);
            }

            return(Result);
        }
Ejemplo n.º 12
0
        public override CPPOutput GenerateISPCHeaders(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
        {
            CPPOutput Result = new CPPOutput();

            if (!CompileEnvironment.bCompileISPC)
            {
                return(Result);
            }

            List <string> CompileTargets = GetISPCCompileTargets(CompileEnvironment.Platform, null);

            foreach (FileItem ISPCFile in InputFiles)
            {
                Action CompileAction = Graph.CreateAction(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";
                CompileAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory;
                CompileAction.CommandPath        = new FileReference(GetISPCHostCompilerPath(BuildHostPlatform.Current.Platform));
                CompileAction.StatusDescription  = Path.GetFileName(ISPCFile.AbsolutePath);

                // Disable remote execution to workaround mismatched case on XGE
                CompileAction.bCanExecuteRemotely = false;

                List <string> Arguments = new List <string>();

                // Add the ISPC obj file as a prerequisite of the action.
                CompileAction.CommandArguments = String.Format("\"{0}\" ", ISPCFile.AbsolutePath);

                // Add the ISPC h file to the produced item list.
                FileItem ISPCIncludeHeaderFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + ".generated.dummy.h"
                        )
                    );

                // Add the ISPC file to be compiled.
                Arguments.Add(String.Format("-h \"{0}\"", ISPCIncludeHeaderFile));

                // Build target string. No comma on last
                string TargetString = "";
                foreach (string Target in CompileTargets)
                {
                    if (Target == CompileTargets[CompileTargets.Count - 1])                   // .Last()
                    {
                        TargetString += Target;
                    }
                    else
                    {
                        TargetString += Target + ",";
                    }
                }

                // Build target triplet
                Arguments.Add(String.Format("--target-os={0}", GetISPCOSTarget(CompileEnvironment.Platform)));
                Arguments.Add(String.Format("--arch={0}", GetISPCArchTarget(CompileEnvironment.Platform, null)));
                Arguments.Add(String.Format("--target={0}", TargetString));

                // PIC is needed for modular builds except on Windows
                if ((CompileEnvironment.bIsBuildingDLL ||
                     CompileEnvironment.bIsBuildingLibrary) &&
                    !UEBuildPlatform.IsPlatformInGroup(CompileEnvironment.Platform, UnrealPlatformGroup.Windows))
                {
                    Arguments.Add("--pic");
                }

                // Include paths. Don't use AddIncludePath() here, since it uses the full path and exceeds the max command line length.
                // Because ISPC response files don't support white space in arguments, paths with white space need to be passed to the command line directly.
                foreach (DirectoryReference IncludePath in CompileEnvironment.UserIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", IncludePath));
                }

                // System include paths.
                foreach (DirectoryReference SystemIncludePath in CompileEnvironment.SystemIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", SystemIncludePath));
                }

                // Generate the included header dependency list
                if (CompileEnvironment.bGenerateDependenciesFile)
                {
                    FileItem DependencyListFile = FileItem.GetItemByFileReference(FileReference.Combine(OutputDir, Path.GetFileName(ISPCFile.AbsolutePath) + ".txt"));
                    Arguments.Add(String.Format("-MMM \"{0}\"", DependencyListFile.AbsolutePath.Replace('\\', '/')));
                    CompileAction.DependencyListFile = DependencyListFile;
                    CompileAction.ProducedItems.Add(DependencyListFile);
                }

                CompileAction.ProducedItems.Add(ISPCIncludeHeaderFile);

                FileReference ResponseFileName = new FileReference(ISPCIncludeHeaderFile.AbsolutePath + ".response");
                FileItem      ResponseFileItem = Graph.CreateIntermediateTextFile(ResponseFileName, Arguments.Select(x => Utils.ExpandVariables(x)));
                CompileAction.CommandArguments += String.Format("@\"{0}\"", ResponseFileName);
                CompileAction.PrerequisiteItems.Add(ResponseFileItem);

                // Add the source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(ISPCFile);

                FileItem ISPCFinalHeaderFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + ".generated.h"
                        )
                    );

                // Fix interrupted build issue by copying header after generation completes
                FileReference SourceFile = ISPCIncludeHeaderFile.Location;
                FileReference TargetFile = ISPCFinalHeaderFile.Location;

                FileItem SourceFileItem = FileItem.GetItemByFileReference(SourceFile);
                FileItem TargetFileItem = FileItem.GetItemByFileReference(TargetFile);

                Action CopyAction = Graph.CreateAction(ActionType.BuildProject);
                CopyAction.CommandDescription = "Copy";
                CopyAction.CommandPath        = BuildHostPlatform.Current.Shell;
                if (BuildHostPlatform.Current.ShellType == ShellType.Cmd)
                {
                    CopyAction.CommandArguments = String.Format("/C \"copy /Y \"{0}\" \"{1}\" 1>nul\"", SourceFile, TargetFile);
                }
                else
                {
                    CopyAction.CommandArguments = String.Format("-c 'cp -f \"{0}\" \"{1}\"'", SourceFile.FullName, TargetFile.FullName);
                }
                CopyAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory;
                CopyAction.PrerequisiteItems.Add(SourceFileItem);
                CopyAction.ProducedItems.Add(TargetFileItem);
                CopyAction.StatusDescription              = TargetFileItem.Location.GetFileName();
                CopyAction.bCanExecuteRemotely            = false;
                CopyAction.bShouldOutputStatusDescription = false;

                Result.GeneratedHeaderFiles.Add(TargetFileItem);

                Log.TraceVerbose("   ISPC Generating Header " + CompileAction.StatusDescription + ": \"" + CompileAction.CommandPath + "\"" + CompileAction.CommandArguments);
            }

            return(Result);
        }