Пример #1
0
        /// <summary>
        /// Patches a set of actions for use with live coding. The new action list will output object files to a different location.
        /// </summary>
        /// <param name="Actions">Set of actions</param>
        /// <param name="OriginalFileToPatchedFile">Dictionary that receives a map of original object file to patched object file</param>
        public static void PatchActionGraphForLiveCoding(IEnumerable <Action> Actions, Dictionary <FileReference, FileReference> OriginalFileToPatchedFile)
        {
            foreach (Action Action in Actions)
            {
                if (Action.ActionType == ActionType.Compile)
                {
                    if (!Action.CommandPath.GetFileName().Equals("cl-filter.exe", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new BuildException("Unable to patch action graph - unexpected executable in compile action ({0})", Action.CommandPath);
                    }

                    List <string> Arguments = Utils.ParseArgumentList(Action.CommandArguments);

                    // Find the index of the cl-filter argument delimiter
                    int DelimiterIdx = Arguments.IndexOf("--");
                    if (DelimiterIdx == -1)
                    {
                        throw new BuildException("Unable to patch action graph - missing '--' delimiter to cl-filter");
                    }

                    // Fix the dependencies path
                    const string DependenciesPrefix = "-dependencies=";

                    int DependenciesIdx = 0;
                    for (;; DependenciesIdx++)
                    {
                        if (DependenciesIdx == DelimiterIdx)
                        {
                            throw new BuildException("Unable to patch action graph - missing '{0}' argument to cl-filter", DependenciesPrefix);
                        }
                        else if (Arguments[DependenciesIdx].StartsWith(DependenciesPrefix, StringComparison.OrdinalIgnoreCase))
                        {
                            break;
                        }
                    }

                    FileReference OldDependenciesFile     = new FileReference(Arguments[DependenciesIdx].Substring(DependenciesPrefix.Length));
                    FileItem      OldDependenciesFileItem = Action.ProducedItems.First(x => x.Location == OldDependenciesFile);
                    Action.ProducedItems.Remove(OldDependenciesFileItem);

                    FileReference NewDependenciesFile     = OldDependenciesFile.ChangeExtension(".lc.response");
                    FileItem      NewDependenciesFileItem = FileItem.GetItemByFileReference(NewDependenciesFile);
                    Action.ProducedItems.Add(NewDependenciesFileItem);

                    Arguments[DependenciesIdx] = DependenciesPrefix + NewDependenciesFile.FullName;

                    // Fix the response file
                    int ResponseFileIdx = DelimiterIdx + 1;
                    for (; ; ResponseFileIdx++)
                    {
                        if (ResponseFileIdx == Arguments.Count)
                        {
                            throw new BuildException("Unable to patch action graph - missing response file argument to cl-filter");
                        }
                        else if (Arguments[ResponseFileIdx].StartsWith("@", StringComparison.Ordinal))
                        {
                            break;
                        }
                    }

                    FileReference OldResponseFile = new FileReference(Arguments[ResponseFileIdx].Substring(1));
                    FileReference NewResponseFile = new FileReference(OldResponseFile.FullName + ".lc");

                    const string OutputFilePrefix = "/Fo";

                    string[] ResponseLines = FileReference.ReadAllLines(OldResponseFile);
                    for (int Idx = 0; Idx < ResponseLines.Length; Idx++)
                    {
                        string ResponseLine = ResponseLines[Idx];
                        if (ResponseLine.StartsWith(OutputFilePrefix, StringComparison.Ordinal))
                        {
                            FileReference OldOutputFile     = new FileReference(ResponseLine.Substring(3).Trim('\"'));
                            FileItem      OldOutputFileItem = Action.ProducedItems.First(x => x.Location == OldOutputFile);
                            Action.ProducedItems.Remove(OldOutputFileItem);

                            FileReference NewOutputFile     = OldOutputFile.ChangeExtension(".lc.obj");
                            FileItem      NewOutputFileItem = FileItem.GetItemByFileReference(NewOutputFile);
                            Action.ProducedItems.Add(NewOutputFileItem);

                            OriginalFileToPatchedFile[OldOutputFile] = NewOutputFile;

                            ResponseLines[Idx] = OutputFilePrefix + "\"" + NewOutputFile.FullName + "\"";
                            break;
                        }
                    }
                    FileReference.WriteAllLines(NewResponseFile, ResponseLines);

                    Arguments[ResponseFileIdx] = "@" + NewResponseFile.FullName;

                    // Update the final arguments
                    Action.CommandArguments = Utils.FormatCommandLine(Arguments);
                }
            }
        }