Exemplo n.º 1
0
 /// <summary>
 /// Inserts variables to make a file relative to $(EngineDir) or $(ProjectDir)
 /// </summary>
 /// <param name="File">The file to insert variables into.</param>
 /// <param name="EngineDir">Value of the $(EngineDir) variable.</param>
 /// <param name="ProjectDir">Value of the $(ProjectDir) variable.</param>
 /// <returns>Converted path for the file.</returns>
 static string InsertPathVariables(FileReference File, DirectoryReference EngineDir, DirectoryReference ProjectDir)
 {
     if (File.IsUnderDirectory(EngineDir))
     {
         return("$(EngineDir)/" + File.MakeRelativeTo(EngineDir).Replace(Path.DirectorySeparatorChar, '/'));
     }
     else if (ProjectDir != null && File.IsUnderDirectory(ProjectDir))
     {
         return("$(ProjectDir)/" + File.MakeRelativeTo(ProjectDir).Replace(Path.DirectorySeparatorChar, '/'));
     }
     else
     {
         return(File.FullName);
     }
 }
Exemplo n.º 2
0
 /// <summary>
 /// Inserts variables to make a file relative to $(EngineDir) or $(ProjectDir)
 /// </summary>
 /// <param name="File">The file to insert variables into.</param>
 /// <param name="EngineDir">Value of the $(EngineDir) variable.</param>
 /// <param name="ProjectDir">Value of the $(ProjectDir) variable.</param>
 /// <returns>Converted path for the file.</returns>
 public static string InsertPathVariables(FileReference File, DirectoryReference EngineDir, DirectoryReference ProjectDir)
 {
     if (File.IsUnderDirectory(EngineDir))
     {
         return("$(EngineDir)" + Path.DirectorySeparatorChar + File.MakeRelativeTo(EngineDir));
     }
     else if (File.IsUnderDirectory(ProjectDir))
     {
         return("$(ProjectDir)" + Path.DirectorySeparatorChar + File.MakeRelativeTo(ProjectDir));
     }
     else
     {
         return(File.FullName);
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Write the receipt to disk.
        /// </summary>
        /// <param name="Location">Output filename</param>
        /// <param name="EngineDir">Engine directory for expanded paths</param>
        public void Write(FileReference Location, DirectoryReference EngineDir)
        {
            using (JsonWriter Writer = new JsonWriter(Location.FullName))
            {
                Writer.WriteObjectStart();
                Writer.WriteValue("TargetName", TargetName);
                Writer.WriteValue("Platform", Platform.ToString());
                Writer.WriteValue("Configuration", Configuration.ToString());
                Writer.WriteValue("TargetType", TargetType.ToString());

                if (ProjectFile != null)
                {
                    Writer.WriteValue("Project", ProjectFile.MakeRelativeTo(Location.Directory).Replace(Path.DirectorySeparatorChar, '/'));
                }

                if (Launch != null)
                {
                    Writer.WriteValue("Launch", InsertPathVariables(Launch, EngineDir, ProjectDir));
                }

                Writer.WriteObjectStart("Version");
                Version.WriteProperties(Writer);
                Writer.WriteObjectEnd();

                Writer.WriteArrayStart("BuildProducts");
                foreach (BuildProduct BuildProduct in BuildProducts)
                {
                    Writer.WriteObjectStart();
                    Writer.WriteValue("Path", InsertPathVariables(BuildProduct.Path, EngineDir, ProjectDir));
                    Writer.WriteValue("Type", BuildProduct.Type.ToString());
                    Writer.WriteObjectEnd();
                }
                Writer.WriteArrayEnd();

                Writer.WriteArrayStart("RuntimeDependencies");
                foreach (RuntimeDependency RuntimeDependency in RuntimeDependencies)
                {
                    Writer.WriteObjectStart();
                    Writer.WriteValue("Path", InsertPathVariables(RuntimeDependency.Path, EngineDir, ProjectDir));
                    Writer.WriteValue("Type", RuntimeDependency.Type.ToString());
                    Writer.WriteObjectEnd();
                }
                Writer.WriteArrayEnd();

                if (AdditionalProperties.Count > 0)
                {
                    Writer.WriteArrayStart("AdditionalProperties");
                    foreach (ReceiptProperty AdditionalProperty in AdditionalProperties)
                    {
                        Writer.WriteObjectStart();
                        Writer.WriteValue("Name", AdditionalProperty.Name);
                        Writer.WriteValue("Value", AdditionalProperty.Value);
                        Writer.WriteObjectEnd();
                    }
                    Writer.WriteArrayEnd();
                }

                Writer.WriteObjectEnd();
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Takes the given path and tries to rebase it relative to the project.
 /// </summary>
 public string NormalizeProjectPath(FileReference InputPath)
 {
     // Try to make it relative to the solution directory.
     if (InputPath.IsUnderDirectory(ProjectFileGenerator.MasterProjectPath))
     {
         return(InputPath.MakeRelativeTo(ProjectFileGenerator.IntermediateProjectFilesPath));
     }
     else
     {
         return(InputPath.FullName);
     }
 }
Exemplo n.º 5
0
 /// <summary>
 /// Adds a rule which matches a filename relative to a given base directory.
 /// </summary>
 /// <param name="File">The filename to add a rule for</param>
 /// <param name="BaseDirectory">Base directory for the rule</param>
 /// <param name="Type">Whether to add an include or exclude rule</param>
 public void AddRuleForFile(FileReference File, DirectoryReference BaseDirectory, FileFilterType Type)
 {
     AddRule("/" + File.MakeRelativeTo(BaseDirectory), Type);
 }
Exemplo n.º 6
0
        /// <summary>
        /// Downloads a single file from the remote
        /// </summary>
        /// <param name="LocalFile">The file to download</param>
        void DownloadFile(FileReference LocalFile)
        {
            RemoteMapping Mapping = Mappings.FirstOrDefault(x => LocalFile.IsUnderDirectory(x.LocalDirectory));

            if (Mapping == null)
            {
                throw new BuildException("File for download '{0}' is not under any mapped directory.", LocalFile);
            }

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

            Arguments.Add(String.Format("\"{0}@{1}\":'{2}/{3}'", UserName, ServerName, Mapping.RemoteDirectory, LocalFile.MakeRelativeTo(Mapping.LocalDirectory).Replace('\\', '/')));
            Arguments.Add(String.Format("\"{0}/\"", GetLocalCygwinPath(LocalFile.Directory)));
            Arguments.Add("-q");

            int Result = Rsync(String.Join(" ", Arguments));

            if (Result != 0)
            {
                throw new BuildException("Unable to download '{0}' from the remote Mac (exit code {1}).", LocalFile, Result);
            }
        }
Exemplo n.º 7
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 ScriptUploadList = FileReference.Combine(TempDir, "RsyncEngineScripts-Upload.txt");

            using (StreamWriter Writer = new StreamWriter(ScriptUploadList.FullName))
            {
                foreach (string ScriptPath in ScriptPaths)
                {
                    for (int SlashIdx = ScriptPath.IndexOf('/', 1); SlashIdx != -1; SlashIdx = ScriptPath.IndexOf('/', SlashIdx + 1))
                    {
                        Writer.WriteLine("+ {0}", ScriptPath.Substring(0, SlashIdx));
                    }
                    Writer.WriteLine("+ {0}", ScriptPath);
                }
                Writer.WriteLine("protect *");
            }

            // 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
            List <FileReference> FilterLocations = new List <FileReference>();

            FilterLocations.Add(ScriptUploadList);
            UploadDirectory(TempDir, GetRemotePath(UnrealBuildTool.EngineDirectory), FilterLocations);

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

            EngineFilters.Add(ScriptProtectList);
            EngineFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngine.txt"));
            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"));

                UploadDirectory(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory), ProjectFilters);
            }
        }
        protected override bool WriteMasterProjectFile(ProjectFile UBTProject, PlatformProjectGeneratorCollection PlatformProjectGenerators)
        {
            bool bSuccess = true;

            string SolutionFileName = MasterProjectName + ".sln";

            // Setup solution file content
            StringBuilder VCSolutionFileContent = new StringBuilder();

            // Solution file header. Note that a leading newline is required for file type detection to work correclty in the shell.
            if (ProjectFileFormat == VCProjectFileFormat.VisualStudio2019)
            {
                VCSolutionFileContent.AppendLine();
                VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                VCSolutionFileContent.AppendLine("# Visual Studio Version 16");
                VCSolutionFileContent.AppendLine("VisualStudioVersion = 16.0.28315.86");
                VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
            }
            else if (ProjectFileFormat == VCProjectFileFormat.VisualStudio2017)
            {
                VCSolutionFileContent.AppendLine();
                VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                VCSolutionFileContent.AppendLine("# Visual Studio 15");
                VCSolutionFileContent.AppendLine("VisualStudioVersion = 15.0.25807.0");
                VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
            }
            else if (ProjectFileFormat == VCProjectFileFormat.VisualStudio2015)
            {
                VCSolutionFileContent.AppendLine();
                VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                VCSolutionFileContent.AppendLine("# Visual Studio 14");
                VCSolutionFileContent.AppendLine("VisualStudioVersion = 14.0.22310.1");
                VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
            }
            else if (ProjectFileFormat == VCProjectFileFormat.VisualStudio2013)
            {
                VCSolutionFileContent.AppendLine();
                VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                VCSolutionFileContent.AppendLine("# Visual Studio 2013");
            }
            else if (ProjectFileFormat == VCProjectFileFormat.VisualStudio2012)
            {
                VCSolutionFileContent.AppendLine();
                VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
                VCSolutionFileContent.AppendLine("# Visual Studio 2012");
            }
            else
            {
                throw new BuildException("Unexpected ProjectFileFormat");
            }

            // Solution folders, files and project entries
            {
                // This the GUID that Visual Studio uses to identify a solution folder
                string SolutionFolderEntryGUID = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}";

                // Solution folders
                {
                    List <MasterProjectFolder> AllSolutionFolders = new List <MasterProjectFolder>();
                    System.Action <List <MasterProjectFolder> /* Folders */> GatherFoldersFunction = null;
                    GatherFoldersFunction = FolderList =>
                    {
                        AllSolutionFolders.AddRange(FolderList);
                        foreach (MasterProjectFolder CurSubFolder in FolderList)
                        {
                            GatherFoldersFunction(CurSubFolder.SubFolders);
                        }
                    };
                    GatherFoldersFunction(RootFolder.SubFolders);

                    AllSolutionFolders.Sort((Lhs, Rhs) => Lhs.FolderName.CompareTo(Rhs.FolderName));

                    foreach (VisualStudioSolutionFolder CurFolder in AllSolutionFolders)
                    {
                        string FolderGUIDString = CurFolder.FolderGUID.ToString("B").ToUpperInvariant();
                        VCSolutionFileContent.AppendLine("Project(\"" + SolutionFolderEntryGUID + "\") = \"" + CurFolder.FolderName + "\", \"" + CurFolder.FolderName + "\", \"" + FolderGUIDString + "\"");

                        // Add any files that are inlined right inside the solution folder
                        if (CurFolder.Files.Count > 0)
                        {
                            VCSolutionFileContent.AppendLine("	ProjectSection(SolutionItems) = preProject");
                            foreach (string CurFile in CurFolder.Files)
                            {
                                // Syntax is:  <relative file path> = <relative file path>
                                VCSolutionFileContent.AppendLine("		"+ CurFile + " = " + CurFile);
                            }
                            VCSolutionFileContent.AppendLine("	EndProjectSection");
                        }

                        VCSolutionFileContent.AppendLine("EndProject");
                    }
                }


                // Project files
                List <MSBuildProjectFile> AllProjectFilesSorted = AllProjectFiles.OrderBy((ProjFile) => ProjFile.ProjectFilePath.GetFileNameWithoutExtension()).Cast <MSBuildProjectFile>().ToList();
                foreach (MSBuildProjectFile CurProject in AllProjectFiles)
                {
                    // Visual Studio uses different GUID types depending on the project type
                    string ProjectTypeGUID = CurProject.ProjectTypeGUID;

                    // NOTE: The project name in the solution doesn't actually *have* to match the project file name on disk.  However,
                    //       we prefer it when it does match so we use the actual file name here.
                    string ProjectNameInSolution = CurProject.ProjectFilePath.GetFileNameWithoutExtension();

                    // Use the existing project's GUID that's already known to us
                    string ProjectGUID = CurProject.ProjectGUID.ToString("B").ToUpperInvariant();

                    VCSolutionFileContent.AppendLine("Project(\"" + ProjectTypeGUID + "\") = \"" + ProjectNameInSolution + "\", \"" + CurProject.ProjectFilePath.MakeRelativeTo(ProjectFileGenerator.MasterProjectPath) + "\", \"" + ProjectGUID + "\"");

                    // Setup dependency on UnrealBuildTool, if we need that.  This makes sure that UnrealBuildTool is
                    // freshly compiled before kicking off any build operations on this target project
                    if (!CurProject.IsStubProject)
                    {
                        List <ProjectFile> Dependencies = new List <ProjectFile>();
                        if (CurProject.IsGeneratedProject && UBTProject != null && CurProject != UBTProject)
                        {
                            Dependencies.Add(UBTProject);
                            Dependencies.AddRange(UBTProject.DependsOnProjects);
                        }
                        Dependencies.AddRange(CurProject.DependsOnProjects);

                        if (Dependencies.Count > 0)
                        {
                            VCSolutionFileContent.AppendLine("\tProjectSection(ProjectDependencies) = postProject");

                            // Setup any addition dependencies this project has...
                            foreach (ProjectFile DependsOnProject in Dependencies)
                            {
                                string DependsOnProjectGUID = ((MSBuildProjectFile)DependsOnProject).ProjectGUID.ToString("B").ToUpperInvariant();
                                VCSolutionFileContent.AppendLine("\t\t" + DependsOnProjectGUID + " = " + DependsOnProjectGUID);
                            }

                            VCSolutionFileContent.AppendLine("\tEndProjectSection");
                        }
                    }

                    VCSolutionFileContent.AppendLine("EndProject");
                }

                // Get the path to the visualizers file. Try to make it relative to the solution directory, but fall back to a full path if it's a foreign project.
                FileReference VisualizersFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "VisualStudioDebugging", "UE4.natvis");

                // Add the visualizers at the solution level. Doesn't seem to be picked up from a makefile project in VS2017 15.8.5.
                VCSolutionFileContent.AppendLine(String.Format("Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"Visualizers\", \"Visualizers\", \"{0}\"", Guid.NewGuid().ToString("B").ToUpperInvariant()));
                VCSolutionFileContent.AppendLine("\tProjectSection(SolutionItems) = preProject");
                VCSolutionFileContent.AppendLine("\t\t{0} = {0}", VisualizersFile.MakeRelativeTo(MasterProjectPath));
                VCSolutionFileContent.AppendLine("\tEndProjectSection");
                VCSolutionFileContent.AppendLine("EndProject");
            }

            // Solution configuration platforms.  This is just a list of all of the platforms and configurations that
            // appear in Visual Studio's build configuration selector.
            List <VCSolutionConfigCombination> SolutionConfigCombinations = new List <VCSolutionConfigCombination>();

            // The "Global" section has source control, solution configurations, project configurations,
            // preferences, and project hierarchy data
            {
                VCSolutionFileContent.AppendLine("Global");
                {
                    {
                        VCSolutionFileContent.AppendLine("	GlobalSection(SolutionConfigurationPlatforms) = preSolution");

                        Dictionary <string, Tuple <UnrealTargetConfiguration, TargetType> > SolutionConfigurationsValidForProjects = new Dictionary <string, Tuple <UnrealTargetConfiguration, TargetType> >();
                        HashSet <UnrealTargetPlatform> PlatformsValidForProjects = new HashSet <UnrealTargetPlatform>();

                        foreach (UnrealTargetConfiguration CurConfiguration in SupportedConfigurations)
                        {
                            if (InstalledPlatformInfo.IsValidConfiguration(CurConfiguration, EProjectType.Code))
                            {
                                foreach (UnrealTargetPlatform CurPlatform in SupportedPlatforms)
                                {
                                    if (InstalledPlatformInfo.IsValidPlatform(CurPlatform, EProjectType.Code))
                                    {
                                        foreach (ProjectFile CurProject in AllProjectFiles)
                                        {
                                            if (!CurProject.IsStubProject)
                                            {
                                                if (CurProject.ProjectTargets.Count == 0)
                                                {
                                                    throw new BuildException("Expecting project '" + CurProject.ProjectFilePath + "' to have at least one ProjectTarget associated with it!");
                                                }

                                                // Figure out the set of valid target configuration names
                                                foreach (ProjectTarget ProjectTarget in CurProject.ProjectTargets)
                                                {
                                                    if (VCProjectFile.IsValidProjectPlatformAndConfiguration(ProjectTarget, CurPlatform, CurConfiguration, PlatformProjectGenerators))
                                                    {
                                                        PlatformsValidForProjects.Add(CurPlatform);

                                                        // Default to a target configuration name of "Game", since that will collapse down to an empty string
                                                        TargetType TargetType = TargetType.Game;
                                                        if (ProjectTarget.TargetRules != null)
                                                        {
                                                            TargetType = ProjectTarget.TargetRules.Type;
                                                        }

                                                        string SolutionConfigName = MakeSolutionConfigurationName(CurConfiguration, TargetType);
                                                        SolutionConfigurationsValidForProjects[SolutionConfigName] = new Tuple <UnrealTargetConfiguration, TargetType>(CurConfiguration, TargetType);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        foreach (UnrealTargetPlatform CurPlatform in PlatformsValidForProjects)
                        {
                            foreach (KeyValuePair <string, Tuple <UnrealTargetConfiguration, TargetType> > SolutionConfigKeyValue in SolutionConfigurationsValidForProjects)
                            {
                                // e.g.  "Development|Win64 = Development|Win64"
                                string SolutionConfigName = SolutionConfigKeyValue.Key;
                                UnrealTargetConfiguration Configuration = SolutionConfigKeyValue.Value.Item1;
                                TargetType TargetType = SolutionConfigKeyValue.Value.Item2;

                                string SolutionPlatformName = CurPlatform.ToString();

                                string SolutionConfigAndPlatformPair = SolutionConfigName + "|" + SolutionPlatformName;
                                SolutionConfigCombinations.Add(
                                    new VCSolutionConfigCombination
                                {
                                    VCSolutionConfigAndPlatformName = SolutionConfigAndPlatformPair,
                                    Configuration           = Configuration,
                                    Platform                = CurPlatform,
                                    TargetConfigurationName = TargetType
                                }
                                    );
                            }
                        }

                        // Sort the list of solution platform strings alphabetically (Visual Studio prefers it)
                        SolutionConfigCombinations.Sort(
                            new Comparison <VCSolutionConfigCombination>(
                                (x, y) => { return(String.Compare(x.VCSolutionConfigAndPlatformName, y.VCSolutionConfigAndPlatformName, StringComparison.InvariantCultureIgnoreCase)); }
                                )
                            );

                        HashSet <string> AppendedSolutionConfigAndPlatformNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
                        foreach (VCSolutionConfigCombination SolutionConfigCombination in SolutionConfigCombinations)
                        {
                            // We alias "Game" and "Program" to both have the same solution configuration, so we're careful not to add the same combination twice.
                            if (!AppendedSolutionConfigAndPlatformNames.Contains(SolutionConfigCombination.VCSolutionConfigAndPlatformName))
                            {
                                VCSolutionFileContent.AppendLine("		"+ SolutionConfigCombination.VCSolutionConfigAndPlatformName + " = " + SolutionConfigCombination.VCSolutionConfigAndPlatformName);
                                AppendedSolutionConfigAndPlatformNames.Add(SolutionConfigCombination.VCSolutionConfigAndPlatformName);
                            }
                        }

                        VCSolutionFileContent.AppendLine("	EndGlobalSection");
                    }


                    // Assign each project's "project configuration" to our "solution platform + configuration" pairs.  This
                    // also sets up which projects are actually built when building the solution.
                    {
                        VCSolutionFileContent.AppendLine("	GlobalSection(ProjectConfigurationPlatforms) = postSolution");

                        foreach (MSBuildProjectFile CurProject in AllProjectFiles)
                        {
                            foreach (VCSolutionConfigCombination SolutionConfigCombination in SolutionConfigCombinations)
                            {
                                // Get the context for the current solution context
                                MSBuildProjectContext ProjectContext = CurProject.GetMatchingProjectContext(SolutionConfigCombination.TargetConfigurationName, SolutionConfigCombination.Configuration, SolutionConfigCombination.Platform, PlatformProjectGenerators);

                                // Write the solution mapping (e.g.  "{4232C52C-680F-4850-8855-DC39419B5E9B}.Debug|iOS.ActiveCfg = iOS_Debug|Win32")
                                string CurProjectGUID = CurProject.ProjectGUID.ToString("B").ToUpperInvariant();
                                VCSolutionFileContent.AppendLine("		{0}.{1}.ActiveCfg = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
                                if (ProjectContext.bBuildByDefault)
                                {
                                    VCSolutionFileContent.AppendLine("		{0}.{1}.Build.0 = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
                                    if (ProjectContext.bDeployByDefault)
                                    {
                                        VCSolutionFileContent.AppendLine("		{0}.{1}.Deploy.0 = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
                                    }
                                }
                            }
                        }

                        VCSolutionFileContent.AppendLine("	EndGlobalSection");
                    }


                    // Setup other solution properties
                    {
                        // HideSolutionNode sets whether or not the top-level solution entry is completely hidden in the UI.
                        // We don't want that, as we need users to be able to right click on the solution tree item.
                        VCSolutionFileContent.AppendLine("	GlobalSection(SolutionProperties) = preSolution");
                        VCSolutionFileContent.AppendLine("		HideSolutionNode = FALSE");
                        VCSolutionFileContent.AppendLine("	EndGlobalSection");
                    }



                    // Solution directory hierarchy
                    {
                        VCSolutionFileContent.AppendLine("	GlobalSection(NestedProjects) = preSolution");

                        // Every entry in this section is in the format "Guid1 = Guid2".  Guid1 is the child project (or solution
                        // filter)'s GUID, and Guid2 is the solution filter directory to parent the child project (or solution
                        // filter) to.  This sets up the hierarchical solution explorer tree for all solution folders and projects.

                        System.Action <StringBuilder /* VCSolutionFileContent */, List <MasterProjectFolder> /* Folders */> FolderProcessorFunction = null;
                        FolderProcessorFunction = (LocalVCSolutionFileContent, LocalMasterProjectFolders) =>
                        {
                            foreach (VisualStudioSolutionFolder CurFolder in LocalMasterProjectFolders)
                            {
                                string CurFolderGUIDString = CurFolder.FolderGUID.ToString("B").ToUpperInvariant();

                                foreach (MSBuildProjectFile ChildProject in CurFolder.ChildProjects)
                                {
                                    //	e.g. "{BF6FB09F-A2A6-468F-BE6F-DEBE07EAD3EA} = {C43B6BB5-3EF0-4784-B896-4099753BCDA9}"
                                    LocalVCSolutionFileContent.AppendLine("		"+ ChildProject.ProjectGUID.ToString("B").ToUpperInvariant() + " = " + CurFolderGUIDString);
                                }

                                foreach (VisualStudioSolutionFolder SubFolder in CurFolder.SubFolders)
                                {
                                    //	e.g. "{BF6FB09F-A2A6-468F-BE6F-DEBE07EAD3EA} = {C43B6BB5-3EF0-4784-B896-4099753BCDA9}"
                                    LocalVCSolutionFileContent.AppendLine("		"+ SubFolder.FolderGUID.ToString("B").ToUpperInvariant() + " = " + CurFolderGUIDString);
                                }

                                // Recurse into subfolders
                                FolderProcessorFunction(LocalVCSolutionFileContent, CurFolder.SubFolders);
                            }
                        };
                        FolderProcessorFunction(VCSolutionFileContent, RootFolder.SubFolders);

                        VCSolutionFileContent.AppendLine("	EndGlobalSection");
                    }
                }

                VCSolutionFileContent.AppendLine("EndGlobal");
            }


            // Save the solution file
            if (bSuccess)
            {
                string SolutionFilePath = FileReference.Combine(MasterProjectPath, SolutionFileName).FullName;
                bSuccess = WriteFileIfChanged(SolutionFilePath, VCSolutionFileContent.ToString());
            }


            // Save a solution config file which selects the development editor configuration by default.
            if (bSuccess && bWriteSolutionOptionFile)
            {
                // Figure out the filename for the SUO file. VS will automatically import the options from earlier versions if necessary.
                FileReference SolutionOptionsFileName;
                switch (ProjectFileFormat)
                {
                case VCProjectFileFormat.VisualStudio2012:
                    SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, Path.ChangeExtension(SolutionFileName, "v11.suo"));
                    break;

                case VCProjectFileFormat.VisualStudio2013:
                    SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, Path.ChangeExtension(SolutionFileName, "v12.suo"));
                    break;

                case VCProjectFileFormat.VisualStudio2015:
                    SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v14", ".suo");
                    break;

                case VCProjectFileFormat.VisualStudio2017:
                    SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v15", ".suo");
                    break;

                case VCProjectFileFormat.VisualStudio2019:
                    SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v15", ".suo");                             // Still uses v15
                    break;

                default:
                    throw new BuildException("Unsupported Visual Studio version");
                }

                // Check it doesn't exist before overwriting it. Since these files store the user's preferences, it'd be bad form to overwrite them.
                if (!FileReference.Exists(SolutionOptionsFileName))
                {
                    DirectoryReference.CreateDirectory(SolutionOptionsFileName.Directory);

                    VCSolutionOptions Options = new VCSolutionOptions(ProjectFileFormat);

                    // Set the default configuration and startup project
                    VCSolutionConfigCombination DefaultConfig = SolutionConfigCombinations.Find(x => x.Configuration == UnrealTargetConfiguration.Development && x.Platform == UnrealTargetPlatform.Win64 && x.TargetConfigurationName == TargetType.Editor);
                    if (DefaultConfig != null)
                    {
                        List <VCBinarySetting> Settings = new List <VCBinarySetting>();
                        Settings.Add(new VCBinarySetting("ActiveCfg", DefaultConfig.VCSolutionConfigAndPlatformName));
                        if (DefaultProject != null)
                        {
                            Settings.Add(new VCBinarySetting("StartupProject", ((MSBuildProjectFile)DefaultProject).ProjectGUID.ToString("B")));
                        }
                        Options.SetConfiguration(Settings);
                    }

                    // Mark all the projects as closed by default, apart from the startup project
                    VCSolutionExplorerState ExplorerState = new VCSolutionExplorerState();
                    if (ProjectFileFormat >= VCProjectFileFormat.VisualStudio2017)
                    {
                        BuildSolutionExplorerState_VS2017(RootFolder, "", ExplorerState, DefaultProject);
                    }
                    else
                    {
                        BuildSolutionExplorerState_VS2015(AllProjectFiles, ExplorerState, DefaultProject, IncludeEnginePrograms);
                    }
                    Options.SetExplorerState(ExplorerState);

                    // Write the file
                    if (Options.Sections.Count > 0)
                    {
                        Options.Write(SolutionOptionsFileName.FullName);
                    }
                }
            }

            return(bSuccess);
        }
Exemplo n.º 9
0
        private void MakePackage(TargetReceipt Receipt, TargetReceipt NewReceipt, WindowsArchitecture Architecture, List <string> UpdatedFiles)
        {
            string OutputName             = String.Format("{0}_{1}_{2}_{3}", Receipt.TargetName, Receipt.Platform, Receipt.Configuration, WindowsExports.GetArchitectureSubpath(Architecture));
            string IntermediateDirectory  = Path.Combine(Receipt.ProjectDir != null ? Receipt.ProjectDir.FullName : UnrealBuildTool.EngineDirectory.FullName, "Intermediate", "Deploy", WindowsExports.GetArchitectureSubpath(Architecture));
            string OutputDirectory        = Receipt.Launch.Directory.FullName;
            string OutputAppX             = Path.Combine(OutputDirectory, OutputName + ".appx");
            string SigningCertificate     = @"Build\HoloLens\SigningCertificate.pfx";
            string SigningCertificatePath = Path.Combine(Receipt.ProjectDir != null ? Receipt.ProjectDir.FullName : UnrealBuildTool.EngineDirectory.FullName, SigningCertificate);

            string MapFilename = Path.Combine(IntermediateDirectory, OutputName + ".pkgmap");
            var    LocalRoot   = Receipt.ProjectDir;
            var    EngineRoot  = UnrealBuildTool.RootDirectory;
            var    AddedFiles  = new Dictionary <string, string>();
            bool   PackageFileNeedToBeUpdated = !File.Exists(OutputAppX);

            DateTime AppXTime = DateTime.Now;

            PackageFileNeedToBeUpdated = true;

            if (!PackageFileNeedToBeUpdated)
            {
                AppXTime = File.GetLastWriteTimeUtc(OutputAppX);
            }

            {
                foreach (var Product in Receipt.BuildProducts)
                {
                    if (Product.Type == BuildProductType.Executable || Product.Type == BuildProductType.DynamicLibrary || Product.Type == BuildProductType.RequiredResource)
                    {
                        string Filename;
                        if (AddedFiles.ContainsKey(Product.Path.FullName))
                        {
                            continue;
                        }

                        if (LocalRoot != null && Product.Path.IsUnderDirectory(LocalRoot))
                        {
                            Filename = Product.Path.MakeRelativeTo(LocalRoot.ParentDirectory);
                        }
                        else if (Product.Path.IsUnderDirectory(EngineRoot))
                        {
                            Filename = Product.Path.MakeRelativeTo(EngineRoot);
                        }
                        else
                        {
                            throw new BuildException("Failed to parse target receipt file.  See log for details.");
                        }

                        AddedFiles.Add(Product.Path.FullName, Filename);
                    }
                }

                foreach (var Dep in Receipt.RuntimeDependencies)
                {
                    if (Dep.Type == StagedFileType.NonUFS)
                    {
                        if (AddedFiles.ContainsKey(Dep.Path.FullName))
                        {
                            continue;
                        }

                        string Filename;
                        if (LocalRoot != null && Dep.Path.IsUnderDirectory(LocalRoot))
                        {
                            Filename = Dep.Path.MakeRelativeTo(LocalRoot.ParentDirectory);
                        }
                        else if (Dep.Path.IsUnderDirectory(EngineRoot))
                        {
                            Filename = Dep.Path.MakeRelativeTo(EngineRoot);
                        }
                        else
                        {
                            throw new BuildException("Failed to parse target receipt file.  See log for details.");
                        }

                        AddedFiles.Add(Dep.Path.FullName, Filename);
                    }
                }
            }

            string ManifestName = String.Format("AppxManifest_{0}.xml", WindowsExports.GetArchitectureSubpath(Architecture));

            AddedFiles.Add(Path.Combine(OutputDirectory, ManifestName), "AppxManifest.xml");

            //manually add resources
            string PriFileName = String.Format("resources_{0}.pri", WindowsExports.GetArchitectureSubpath(Architecture));

            AddedFiles.Add(Path.Combine(OutputDirectory, PriFileName), "resources.pri");
            {
                DirectoryReference ResourceFolder = DirectoryReference.Combine(Receipt.Launch.Directory, WindowsExports.GetArchitectureSubpath(Architecture));
                foreach (var ResourcePath in UpdatedFiles)
                {
                    var ResourceFile = new FileReference(ResourcePath);

                    if (ResourceFile.IsUnderDirectory(ResourceFolder))
                    {
                        AddedFiles.Add(ResourceFile.FullName, ResourceFile.MakeRelativeTo(ResourceFolder));
                    }
                    else
                    {
                        Log.TraceError("Wrong path to resource \'{0}\', the resource should be in \'{1}\'", ResourceFile.FullName, ResourceFolder.FullName);
                        throw new BuildException("Failed to generate AppX file.  See log for details.");
                    }
                }
            }


            FileReference SourceNetworkManifestPath = new FileReference(Path.Combine(OutputDirectory, "NetworkManifest.xml"));

            if (FileReference.Exists(SourceNetworkManifestPath))
            {
                AddedFiles.Add(SourceNetworkManifestPath.FullName, "NetworkManifest.xml");
            }
            FileReference SourceXboxConfigPath = new FileReference(Path.Combine(OutputDirectory, "xboxservices.config"));

            if (FileReference.Exists(SourceXboxConfigPath))
            {
                AddedFiles.Add(SourceXboxConfigPath.FullName, "xboxservices.config");
            }

            do
            {
                if (PackageFileNeedToBeUpdated)
                {
                    break;
                }

                if (!File.Exists(MapFilename))
                {
                    PackageFileNeedToBeUpdated = true;
                    break;
                }
                string[] lines      = File.ReadAllLines(MapFilename, Encoding.UTF8);
                int      filesCount = 0;

                foreach (var line in lines)
                {
                    if (line[0] == '[')
                    {
                        continue;
                    }

                    string[] files = line.Split('\t');

                    if (files.Length != 2)
                    {
                        PackageFileNeedToBeUpdated = true;
                        break;
                    }

                    files[0] = files[0].Trim('\"');
                    files[1] = files[1].Trim('\"');

                    if (!AddedFiles.ContainsKey(files[0]))
                    {
                        PackageFileNeedToBeUpdated = true;
                        break;
                    }

                    if (AddedFiles[files[0]] != files[1])
                    {
                        PackageFileNeedToBeUpdated = true;
                        break;
                    }

                    if (File.GetLastWriteTimeUtc(files[0]).CompareTo(AppXTime) >= 0)
                    {
                        PackageFileNeedToBeUpdated = true;
                        break;
                    }

                    ++filesCount;
                }

                if (PackageFileNeedToBeUpdated)
                {
                    break;
                }

                if (filesCount != AddedFiles.Count)
                {
                    PackageFileNeedToBeUpdated = true;
                    break;
                }

                if (File.Exists(SigningCertificatePath) && File.GetLastWriteTimeUtc(SigningCertificatePath).CompareTo(AppXTime) >= 0)
                {
                    PackageFileNeedToBeUpdated = true;
                    break;
                }
            }while(false);

            if (!PackageFileNeedToBeUpdated)
            {
                NewReceipt.BuildProducts.Add(new BuildProduct(new FileReference(OutputAppX), BuildProductType.Package));
                return;
            }

            try
            {
                DeployHelper_DeleteFile(OutputAppX);
            }
            catch (Exception exceptionMessage)
            {
                Log.TraceError("Failed to delete {0} from deployment: {1}", OutputAppX, exceptionMessage);
                throw new BuildException("Failed to generate AppX file.  See log for details.");
            }

            var AppXRecipeBuiltFiles = new StringBuilder();

            AppXRecipeBuiltFiles.AppendLine(@"[Files]");
            foreach (var f in AddedFiles)
            {
                AppXRecipeBuiltFiles.AppendLine(String.Format("\"{0}\"\t\"{1}\"", f.Key, f.Value));
            }
            File.WriteAllText(MapFilename, AppXRecipeBuiltFiles.ToString(), Encoding.UTF8);

            NewReceipt.BuildProducts.Add(new BuildProduct(new FileReference(MapFilename), BuildProductType.MapFile));
        }