Ejemplo n.º 1
0
        /// <summary>
        /// Whether the path contains a valid clang version
        /// </summary>
        private static bool IsValidClangPath(DirectoryReference BaseLinuxPath)
        {
            FileReference ClangPath = FileReference.Combine(BaseLinuxPath, @"bin", (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64) ? "clang++.exe" : "clang++");

            return(FileReference.Exists(ClangPath));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parse crypto settings from INI file
        /// </summary>
        public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform)
        {
            CryptoSettings Settings = new CryptoSettings();

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform);

            Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired);

            {
                // Start by parsing the legacy encryption.ini settings
                Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform);
                Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning);

                string[] SigningKeyStrings = new string[3];
                Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]);
                Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]);
                Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]);

                if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2]))
                {
                    SigningKeyStrings = null;
                }
                else
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[0]), 64);
                    Settings.SigningKey.PrivateKey.Modulus  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[1]), 64);
                    Settings.SigningKey.PublicKey.Exponent  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[2]), 64);
                    Settings.SigningKey.PublicKey.Modulus   = Settings.SigningKey.PrivateKey.Modulus;

                    if ((Settings.SigningKey.PrivateKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PrivateKey.Modulus.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Modulus.Length > 64))
                    {
                        throw new Exception(string.Format("[{0}] Signing keys parsed from encryption.ini are too long. They must be a maximum of 64 bytes long!", InProjectDirectory));
                    }
                }

                Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption);
                Settings.bEnablePakFullAssetEncryption = false;
                Settings.bEnablePakUAssetEncryption    = false;
                Settings.bEnablePakIniEncryption       = Settings.bEnablePakIndexEncryption;

                string EncryptionKeyString;
                Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString);
                Settings.EncryptionKey = new EncryptionKey();

                if (EncryptionKeyString.Length > 0)
                {
                    if (EncryptionKeyString.Length < 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too short. It must be 32 bytes, so will be padded with 0s, giving sub-optimal security!");
                    }
                    else if (EncryptionKeyString.Length > 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too long. It must be 32 bytes, so will be truncated!");
                    }

                    Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString, 32);
                }
            }

            Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform);
            string SectionName = "/Script/CryptoKeys.CryptoKeysSettings";
            ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName);

            // If we have new format crypto keys, read them in over the top of the legacy settings
            if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0)
            {
                Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning);
                Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption);
                Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption);
                Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption);
                Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption);

                // Parse encryption key
                string EncryptionKeyString;
                Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString);
                if (!string.IsNullOrEmpty(EncryptionKeyString))
                {
                    Settings.EncryptionKey     = new EncryptionKey();
                    Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString);
                }

                // Parse secondary encryption keys
                List <EncryptionKey> SecondaryEncryptionKeys = new List <EncryptionKey>();
                List <string>        SecondaryEncryptionKeyStrings;

                if (Ini.GetArray(SectionName, "SecondaryEncryptionKeys", out SecondaryEncryptionKeyStrings))
                {
                    foreach (string KeySource in SecondaryEncryptionKeyStrings)
                    {
                        EncryptionKey NewKey = new EncryptionKey();
                        SecondaryEncryptionKeys.Add(NewKey);

                        Regex Search = new Regex("\\(Guid=(?\'Guid\'.*),Name=\\\"(?\'Name\'.*)\\\",Key=\\\"(?\'Key\'.*)\\\"\\)");
                        Match Match  = Search.Match(KeySource);
                        if (Match.Success)
                        {
                            foreach (string GroupName in Search.GetGroupNames())
                            {
                                string Value = Match.Groups[GroupName].Value;
                                if (GroupName == "Guid")
                                {
                                    NewKey.Guid = Value;
                                }
                                else if (GroupName == "Name")
                                {
                                    NewKey.Name = Value;
                                }
                                else if (GroupName == "Key")
                                {
                                    NewKey.Key = System.Convert.FromBase64String(Value);
                                }
                            }
                        }
                    }
                }

                Settings.SecondaryEncryptionKeys = SecondaryEncryptionKeys.ToArray();

                // Parse signing key
                string PrivateExponent, PublicExponent, Modulus;
                Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent);
                Ini.GetString(SectionName, "SigningModulus", out Modulus);
                Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent);

                if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus))
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PublicKey.Exponent  = System.Convert.FromBase64String(PublicExponent);
                    Settings.SigningKey.PublicKey.Modulus   = System.Convert.FromBase64String(Modulus);
                    Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent);
                    Settings.SigningKey.PrivateKey.Modulus  = Settings.SigningKey.PublicKey.Modulus;
                }
            }

            // Parse project dynamic keychain keys
            if (InProjectDirectory != null)
            {
                ConfigHierarchy GameIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, InProjectDirectory, InTargetPlatform);
                if (GameIni != null)
                {
                    string Filename;
                    if (GameIni.GetString("ContentEncryption", "ProjectKeyChain", out Filename))
                    {
                        FileReference ProjectKeyChainFile = FileReference.Combine(InProjectDirectory, "Content", Filename);
                        if (FileReference.Exists(ProjectKeyChainFile))
                        {
                            List <EncryptionKey> EncryptionKeys = new List <EncryptionKey>(Settings.SecondaryEncryptionKeys);

                            string[] Lines = FileReference.ReadAllLines(ProjectKeyChainFile);
                            foreach (string Line in Lines)
                            {
                                string[] KeyParts = Line.Split(':');
                                if (KeyParts.Length == 4)
                                {
                                    EncryptionKey NewKey = new EncryptionKey();

                                    NewKey.Name = KeyParts[0];
                                    NewKey.Guid = KeyParts[2];
                                    NewKey.Key  = System.Convert.FromBase64String(KeyParts[3]);

                                    if (EncryptionKeys.Find((EncryptionKey OtherKey) => { return(OtherKey.Guid == NewKey.Guid); }) != null)
                                    {
                                        throw new Exception("Found a duplicated encryption key guid when merging a project keychain into the secondary key list");
                                    }

                                    EncryptionKeys.Add(NewKey);
                                }
                            }

                            Settings.SecondaryEncryptionKeys = EncryptionKeys.ToArray();
                        }
                    }
                }
            }

            if (!Settings.bDataCryptoRequired)
            {
                CryptoSettings NewSettings = new CryptoSettings();
                NewSettings.SecondaryEncryptionKeys = Settings.SecondaryEncryptionKeys;
                Settings = NewSettings;
            }

            return(Settings);
        }
        /// <summary>
        /// Generates documentation files for the available settings, by merging the XML documentation from the compiler.
        /// </summary>
        /// <param name="OutputFile">The documentation file to write</param>
        public static void WriteDocumentation(FileReference OutputFile)
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

            // Find all the configurable fields from the given types
            Dictionary <string, Dictionary <string, FieldInfo> > CategoryToFields = new Dictionary <string, Dictionary <string, FieldInfo> >();

            FindConfigurableFields(ConfigTypes, CategoryToFields);

            // Get the path to the XML documentation
            FileReference InputDocumentationFile = new FileReference(Assembly.GetExecutingAssembly().Location).ChangeExtension(".xml");

            if (!FileReference.Exists(InputDocumentationFile))
            {
                throw new BuildException("Generated assembly documentation not found at {0}.", InputDocumentationFile);
            }

            // Get the current engine version for versioning the page
            BuildVersion Version;

            if (!BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
            {
                throw new BuildException("Unable to read the current build version");
            }

            // Read the documentation
            XmlDocument InputDocumentation = new XmlDocument();

            InputDocumentation.Load(InputDocumentationFile.FullName);

            // Make sure we can write to the output file
            FileReference.MakeWriteable(OutputFile);

            // Generate the UDN documentation file
            using (StreamWriter Writer = new StreamWriter(OutputFile.FullName))
            {
                Writer.WriteLine("Availability: NoPublish");
                Writer.WriteLine("Title: Build Configuration Properties Page");
                Writer.WriteLine("Crumbs:");
                Writer.WriteLine("Description: This is a procedurally generated markdown page.");
                Writer.WriteLine("Version: {0}.{1}", Version.MajorVersion, Version.MinorVersion);
                Writer.WriteLine("");

                foreach (KeyValuePair <string, Dictionary <string, FieldInfo> > CategoryPair in CategoryToFields)
                {
                    string CategoryName = CategoryPair.Key;
                    Writer.WriteLine("### {0}", CategoryName);
                    Writer.WriteLine();

                    Dictionary <string, FieldInfo> Fields = CategoryPair.Value;
                    foreach (KeyValuePair <string, FieldInfo> FieldPair in Fields)
                    {
                        string FieldName = FieldPair.Key;

                        FieldInfo Field = FieldPair.Value;
                        XmlNode   Node  = InputDocumentation.SelectSingleNode(String.Format("//member[@name='F:{0}.{1}']/summary", Field.DeclaringType.FullName, Field.Name));
                        if (Node != null)
                        {
                            // Reflow the comments into paragraphs, assuming that each paragraph will be separated by a blank line
                            List <string> Lines = new List <string>(Node.InnerText.Trim().Split('\n').Select(x => x.Trim()));
                            for (int Idx = Lines.Count - 1; Idx > 0; Idx--)
                            {
                                if (Lines[Idx - 1].Length > 0 && !Lines[Idx].StartsWith("*") && !Lines[Idx].StartsWith("-"))
                                {
                                    Lines[Idx - 1] += " " + Lines[Idx];
                                    Lines.RemoveAt(Idx);
                                }
                            }

                            // Write the result to the .udn file
                            if (Lines.Count > 0)
                            {
                                Writer.WriteLine("$ {0} : {1}", FieldName, Lines[0]);
                                for (int Idx = 1; Idx < Lines.Count; Idx++)
                                {
                                    if (Lines[Idx].StartsWith("*") || Lines[Idx].StartsWith("-"))
                                    {
                                        Writer.WriteLine("        * {0}", Lines[Idx].Substring(1).TrimStart());
                                    }
                                    else
                                    {
                                        Writer.WriteLine("    * {0}", Lines[Idx]);
                                    }
                                }
                                Writer.WriteLine();
                            }
                        }
                    }
                }
            }

            // Success!
            Log.TraceInformation("Written documentation to {0}.", OutputFile);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Setup the target environment for building
        /// </summary>
        /// <param name="Target">Settings for the target being compiled</param>
        /// <param name="CompileEnvironment">The compile environment for this target</param>
        /// <param name="LinkEnvironment">The link environment for this target</param>
        public override void SetUpEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment)
        {
            CompileEnvironment.Definitions.Add("WIN32=1");

            if (WindowsPlatform.bUseWindowsSDK10)
            {
                // Windows 8 or higher required
                CompileEnvironment.Definitions.Add("_WIN32_WINNT=0x0602");
                CompileEnvironment.Definitions.Add("WINVER=0x0602");
            }
            else
            {
                // Windows 7 or higher required
                CompileEnvironment.Definitions.Add("_WIN32_WINNT=0x0601");
                CompileEnvironment.Definitions.Add("WINVER=0x0601");
            }
            CompileEnvironment.Definitions.Add("PLATFORM_WINDOWS=1");

            CompileEnvironment.Definitions.Add("DEPTH_32_BIT_CONVERSION=0");

            FileReference MorpheusShaderPath = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Shaders", "PS4", "PostProcessHMDMorpheus.usf");

            if (FileReference.Exists(MorpheusShaderPath))
            {
                CompileEnvironment.Definitions.Add("HAS_MORPHEUS=1");

                //on PS4 the SDK now handles distortion correction.  On PC we will still have to handle it manually,
                CompileEnvironment.Definitions.Add("MORPHEUS_ENGINE_DISTORTION=1");
            }

            // Add path to Intel math libraries when using ICL based on target platform
            if (WindowsPlatform.bCompileWithICL)
            {
                var Result = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "IntelSWTools", "compilers_and_libraries", "windows", "compiler", "lib", Target.Platform == UnrealTargetPlatform.Win32 ? "ia32" : "intel64");
                if (!Directory.Exists(Result))
                {
                    throw new BuildException("ICL was selected but the required math libraries were not found.  Could not find: " + Result);
                }

                LinkEnvironment.LibraryPaths.Add(Result);
            }

            // Explicitly exclude the MS C++ runtime libraries we're not using, to ensure other libraries we link with use the same
            // runtime library as the engine.
            bool bUseDebugCRT = Target.Configuration == UnrealTargetConfiguration.Debug && Target.bDebugBuildsActuallyUseDebugCRT;

            if (!Target.bUseStaticCRT || bUseDebugCRT)
            {
                LinkEnvironment.ExcludedLibraries.Add("LIBCMT");
                LinkEnvironment.ExcludedLibraries.Add("LIBCPMT");
            }
            if (!Target.bUseStaticCRT || !bUseDebugCRT)
            {
                LinkEnvironment.ExcludedLibraries.Add("LIBCMTD");
                LinkEnvironment.ExcludedLibraries.Add("LIBCPMTD");
            }
            if (Target.bUseStaticCRT || bUseDebugCRT)
            {
                LinkEnvironment.ExcludedLibraries.Add("MSVCRT");
                LinkEnvironment.ExcludedLibraries.Add("MSVCPRT");
            }
            if (Target.bUseStaticCRT || !bUseDebugCRT)
            {
                LinkEnvironment.ExcludedLibraries.Add("MSVCRTD");
                LinkEnvironment.ExcludedLibraries.Add("MSVCPRTD");
            }
            LinkEnvironment.ExcludedLibraries.Add("LIBC");
            LinkEnvironment.ExcludedLibraries.Add("LIBCP");
            LinkEnvironment.ExcludedLibraries.Add("LIBCD");
            LinkEnvironment.ExcludedLibraries.Add("LIBCPD");

            //@todo ATL: Currently, only VSAccessor requires ATL (which is only used in editor builds)
            // When compiling games, we do not want to include ATL - and we can't when compiling games
            // made with Launcher build due to VS 2012 Express not including ATL.
            // If more modules end up requiring ATL, this should be refactored into a BuildTarget flag (bNeedsATL)
            // that is set by the modules the target includes to allow for easier tracking.
            // Alternatively, if VSAccessor is modified to not require ATL than we should always exclude the libraries.
            if (Target.LinkType == TargetLinkType.Monolithic &&
                (Target.Type == TargetType.Game || Target.Type == TargetType.Client || Target.Type == TargetType.Server))
            {
                LinkEnvironment.ExcludedLibraries.Add("atl");
                LinkEnvironment.ExcludedLibraries.Add("atls");
                LinkEnvironment.ExcludedLibraries.Add("atlsd");
                LinkEnvironment.ExcludedLibraries.Add("atlsn");
                LinkEnvironment.ExcludedLibraries.Add("atlsnd");
            }

            // Add the library used for the delayed loading of DLLs.
            LinkEnvironment.AdditionalLibraries.Add("delayimp.lib");

            //@todo - remove once FB implementation uses Http module
            if (Target.bCompileAgainstEngine)
            {
                // link against wininet (used by FBX and Facebook)
                LinkEnvironment.AdditionalLibraries.Add("wininet.lib");
            }

            // Compile and link with Win32 API libraries.
            LinkEnvironment.AdditionalLibraries.Add("rpcrt4.lib");
            //LinkEnvironment.AdditionalLibraries.Add("wsock32.lib");
            LinkEnvironment.AdditionalLibraries.Add("ws2_32.lib");
            LinkEnvironment.AdditionalLibraries.Add("dbghelp.lib");
            LinkEnvironment.AdditionalLibraries.Add("comctl32.lib");
            LinkEnvironment.AdditionalLibraries.Add("Winmm.lib");
            LinkEnvironment.AdditionalLibraries.Add("kernel32.lib");
            LinkEnvironment.AdditionalLibraries.Add("user32.lib");
            LinkEnvironment.AdditionalLibraries.Add("gdi32.lib");
            LinkEnvironment.AdditionalLibraries.Add("winspool.lib");
            LinkEnvironment.AdditionalLibraries.Add("comdlg32.lib");
            LinkEnvironment.AdditionalLibraries.Add("advapi32.lib");
            LinkEnvironment.AdditionalLibraries.Add("shell32.lib");
            LinkEnvironment.AdditionalLibraries.Add("ole32.lib");
            LinkEnvironment.AdditionalLibraries.Add("oleaut32.lib");
            LinkEnvironment.AdditionalLibraries.Add("uuid.lib");
            LinkEnvironment.AdditionalLibraries.Add("odbc32.lib");
            LinkEnvironment.AdditionalLibraries.Add("odbccp32.lib");
            LinkEnvironment.AdditionalLibraries.Add("netapi32.lib");
            LinkEnvironment.AdditionalLibraries.Add("iphlpapi.lib");
            LinkEnvironment.AdditionalLibraries.Add("setupapi.lib");             //  Required for access monitor device enumeration

            // Windows Vista/7 Desktop Windows Manager API for Slate Windows Compliance
            LinkEnvironment.AdditionalLibraries.Add("dwmapi.lib");

            // IME
            LinkEnvironment.AdditionalLibraries.Add("imm32.lib");

            // For 64-bit builds, we'll forcibly ignore a linker warning with DirectInput.  This is
            // Microsoft's recommended solution as they don't have a fixed .lib for us.
            if (Target.Platform == UnrealTargetPlatform.Win64)
            {
                LinkEnvironment.AdditionalArguments += " /ignore:4078";
            }

            if (Target.Type != TargetType.Editor)
            {
                if (!string.IsNullOrEmpty(Target.WindowsPlatform.CompanyName))
                {
                    CompileEnvironment.Definitions.Add(String.Format("PROJECT_COMPANY_NAME={0}", SanitizeMacroValue(Target.WindowsPlatform.CompanyName)));
                }

                if (!string.IsNullOrEmpty(Target.WindowsPlatform.CopyrightNotice))
                {
                    CompileEnvironment.Definitions.Add(String.Format("PROJECT_COPYRIGHT_STRING={0}", SanitizeMacroValue(Target.WindowsPlatform.CopyrightNotice)));
                }

                if (!string.IsNullOrEmpty(Target.WindowsPlatform.ProductName))
                {
                    CompileEnvironment.Definitions.Add(String.Format("PROJECT_PRODUCT_NAME={0}", SanitizeMacroValue(Target.WindowsPlatform.ProductName)));
                }

                if (Target.ProjectFile != null)
                {
                    CompileEnvironment.Definitions.Add(String.Format("PROJECT_PRODUCT_IDENTIFIER={0}", SanitizeMacroValue(Target.ProjectFile.GetFileNameWithoutExtension())));
                }
            }

            // Set up default stack size
            ConfigHierarchy EngineIni             = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), UnrealTargetPlatform.Win64);
            String          TargetSettingsIniPath = "/Script/WindowsTargetPlatform.WindowsTargetSettings";
            int             IniDefaultStackSize   = 0;
            String          StackSizeName         = Target.Type == TargetType.Editor ? "DefaultStackSizeEditor" : "DefaultStackSize";

            if (EngineIni.GetInt32(TargetSettingsIniPath, StackSizeName, out IniDefaultStackSize))
            {
                LinkEnvironment.DefaultStackSize = IniDefaultStackSize;
            }

            int    IniDefaultStackSizeCommit = 0;
            String StackSizeCommitName       = Target.Type == TargetType.Editor ? "DefaultStackSizeCommitEditor" : "DefaultStackSizeCommit";

            if (EngineIni.GetInt32(TargetSettingsIniPath, StackSizeCommitName, out IniDefaultStackSizeCommit))
            {
                LinkEnvironment.DefaultStackSizeCommit = IniDefaultStackSizeCommit;
            }
        }
Ejemplo n.º 5
0
        protected IOSProvisioningData(IOSProjectSettings ProjectSettings, bool bIsTVOS, bool bForDistribtion)
        {
            SigningCertificate = ProjectSettings.SigningCertificate;
            string MobileProvision = ProjectSettings.MobileProvision;

            FileReference ProjectFile = ProjectSettings.ProjectFile;

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

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

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

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

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

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

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

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

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

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

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

                if (string.IsNullOrEmpty(MobileProvisionUUID) || string.IsNullOrEmpty(TeamUUID))
                {
                    MobileProvision    = null;
                    SigningCertificate = null;
                    Log.TraceLog("Failed to parse the mobile provisioning profile.");
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Initialize the config system with the given types
        /// </summary>
        /// <param name="OverrideCacheFile">Force use of the cached XML config without checking if it's valid (useful for remote builds)</param>
        public static void ReadConfigFiles(FileReference OverrideCacheFile)
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

            // Update the cache if necessary
            if (OverrideCacheFile != null)
            {
                // Set the cache file to the overriden value
                CacheFile = OverrideCacheFile;

                // Never rebuild the cache; just try to load it.
                if (!XmlConfigData.TryRead(CacheFile, ConfigTypes, out Values))
                {
                    throw new BuildException("Unable to load XML config cache ({0})", CacheFile);
                }
            }
            else
            {
                // Get the default cache file
                CacheFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "XmlConfigCache.bin");
                if (UnrealBuildTool.IsEngineInstalled())
                {
                    DirectoryReference UserSettingsDir = Utils.GetUserSettingDirectory();
                    if (UserSettingsDir != null)
                    {
                        CacheFile = FileReference.Combine(UserSettingsDir, "UnrealEngine", String.Format("XmlConfigCache-{0}.bin", UnrealBuildTool.RootDirectory.FullName.Replace(":", "").Replace(Path.DirectorySeparatorChar, '+')));
                    }
                }

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

                // Get the path to the schema
                FileReference SchemaFile = GetSchemaLocation();

                // Try to read the existing cache from disk
                XmlConfigData CachedValues;
                if (IsCacheUpToDate(CacheFile, InputFiles) && FileReference.Exists(SchemaFile))
                {
                    if (XmlConfigData.TryRead(CacheFile, ConfigTypes, out CachedValues) && Enumerable.SequenceEqual(InputFiles, CachedValues.InputFiles))
                    {
                        Values = CachedValues;
                    }
                }

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

                    // Create a schema for the config files
                    XmlSchema Schema = CreateSchema(CategoryToFields);
                    if (!UnrealBuildTool.IsEngineInstalled())
                    {
                        WriteSchema(Schema, SchemaFile);
                    }

                    // Read all the XML files and validate them against the schema
                    Dictionary <Type, Dictionary <FieldInfo, object> > TypeToValues = new Dictionary <Type, Dictionary <FieldInfo, object> >();
                    foreach (FileReference InputFile in InputFiles)
                    {
                        if (!TryReadFile(InputFile, CategoryToFields, TypeToValues, Schema))
                        {
                            throw new BuildException("Failed to properly read XML file : {0}", InputFile.FullName);
                        }
                    }

                    // Make sure the cache directory exists
                    DirectoryReference.CreateDirectory(CacheFile.Directory);

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

            // Apply all the static field values
            foreach (KeyValuePair <Type, KeyValuePair <FieldInfo, object>[]> TypeValuesPair in Values.TypeToValues)
            {
                foreach (KeyValuePair <FieldInfo, object> FieldValuePair in TypeValuesPair.Value)
                {
                    if (FieldValuePair.Key.IsStatic)
                    {
                        object Value = InstanceValue(FieldValuePair.Value, FieldValuePair.Key.FieldType);
                        FieldValuePair.Key.SetValue(null, Value);
                    }
                }
            }
        }
        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));
        }
Ejemplo n.º 8
0
        public override void CleanProjectFiles(DirectoryReference InMasterProjectDirectory, string InMasterProjectName, DirectoryReference InIntermediateProjectFilesDirectory)
        {
            // Remove Project File
            FileReference MasterProjectFile = FileReference.Combine(InMasterProjectDirectory, ProjectFileName);

            if (FileReference.Exists(MasterProjectFile))
            {
                FileReference.Delete(MasterProjectFile);
            }

            // Remove Headers Files
            FileReference EngineHeadersFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeEngineHeadersFileName);

            if (FileReference.Exists(EngineHeadersFile))
            {
                FileReference.Delete(EngineHeadersFile);
            }
            FileReference ProjectHeadersFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeProjectHeadersFileName);

            if (FileReference.Exists(ProjectHeadersFile))
            {
                FileReference.Delete(ProjectHeadersFile);
            }

            // Remove Sources Files
            FileReference EngineSourcesFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeEngineSourcesFileName);

            if (FileReference.Exists(EngineSourcesFile))
            {
                FileReference.Delete(EngineSourcesFile);
            }
            FileReference ProjectSourcesFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeProjectSourcesFileName);

            if (FileReference.Exists(ProjectSourcesFile))
            {
                FileReference.Delete(ProjectSourcesFile);
            }

            // Remove Includes File
            FileReference IncludeFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeIncludesFileName);

            if (FileReference.Exists(IncludeFile))
            {
                FileReference.Delete(IncludeFile);
            }

            // Remove CSharp Files
            FileReference EngineCSFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeEngineCSFileName);

            if (FileReference.Exists(EngineCSFile))
            {
                FileReference.Delete(EngineCSFile);
            }
            FileReference ProjectCSFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeProjectCSFileName);

            if (FileReference.Exists(ProjectCSFile))
            {
                FileReference.Delete(ProjectCSFile);
            }

            // Remove Config Files
            FileReference EngineConfigFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeEngineConfigsFileName);

            if (FileReference.Exists(EngineConfigFile))
            {
                FileReference.Delete(EngineConfigFile);
            }
            FileReference ProjectConfigsFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeProjectConfigsFileName);

            if (FileReference.Exists(ProjectConfigsFile))
            {
                FileReference.Delete(ProjectConfigsFile);
            }

            // Remove Config Files
            FileReference EngineShadersFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeEngineShadersFileName);

            if (FileReference.Exists(EngineShadersFile))
            {
                FileReference.Delete(EngineShadersFile);
            }
            FileReference ProjectShadersFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeProjectShadersFileName);

            if (FileReference.Exists(ProjectShadersFile))
            {
                FileReference.Delete(ProjectShadersFile);
            }

            // Remove Definitions File
            FileReference DefinitionsFile = FileReference.Combine(InIntermediateProjectFilesDirectory, CMakeDefinitionsFileName);

            if (FileReference.Exists(DefinitionsFile))
            {
                FileReference.Delete(DefinitionsFile);
            }
        }
        public static void WriteDocumentation(Type RulesType, FileReference OutputFile)
        {
            // Get the path to the XML documentation
            FileReference InputDocumentationFile = new FileReference(Assembly.GetExecutingAssembly().Location).ChangeExtension(".xml");

            if (!FileReference.Exists(InputDocumentationFile))
            {
                throw new BuildException("Generated assembly documentation not found at {0}.", InputDocumentationFile);
            }

            // Read the documentation
            XmlDocument InputDocumentation = new XmlDocument();

            InputDocumentation.Load(InputDocumentationFile.FullName);

            // Filter the properties into read-only and read/write lists
            List <FieldInfo> ReadOnlyFields  = new List <FieldInfo>();
            List <FieldInfo> ReadWriteFields = new List <FieldInfo>();

            foreach (FieldInfo Field in RulesType.GetFields(BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public))
            {
                if (!Field.FieldType.IsClass || !Field.FieldType.Name.EndsWith("TargetRules"))
                {
                    if (Field.IsInitOnly)
                    {
                        ReadOnlyFields.Add(Field);
                    }
                    else
                    {
                        ReadWriteFields.Add(Field);
                    }
                }
            }

            // Make sure the output file is writable
            if (FileReference.Exists(OutputFile))
            {
                FileReference.MakeWriteable(OutputFile);
            }
            else
            {
                DirectoryReference.CreateDirectory(OutputFile.Directory);
            }

            // Generate the documentation file
            if (OutputFile.HasExtension(".udn"))
            {
                WriteDocumentationUDN(OutputFile, ReadOnlyFields, ReadWriteFields, InputDocumentation);
            }
            else if (OutputFile.HasExtension(".html"))
            {
                WriteDocumentationHTML(OutputFile, ReadOnlyFields, ReadWriteFields, InputDocumentation);
            }
            else
            {
                throw new BuildException("Unable to detect format from extension of output file ({0})", OutputFile);
            }

            // Success!
            Log.TraceInformation("Written documentation to {0}.", OutputFile);
        }
Ejemplo n.º 10
0
        public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly, List <Action> Actions)
        {
            FileItem OutputFile;

            // Make the final javascript file
            Action LinkAction = new Action(ActionType.Link);

            LinkAction.CommandDescription = "Link";
//			LinkAction.bPrintDebugInfo = true;

            // ResponseFile lines.
            List <string> ReponseLines = new List <string>();

            LinkAction.bCanExecuteRemotely = false;
            LinkAction.WorkingDirectory    = UnrealBuildTool.EngineSourceDirectory;
            LinkAction.CommandPath         = HTML5SDKInfo.Python();
            LinkAction.CommandArguments    = HTML5SDKInfo.EmscriptenCompiler();
//			bool bIsBuildingLibrary = LinkEnvironment.bIsBuildingLibrary || bBuildImportLibraryOnly;
//			ReponseLines.Add(
//					bIsBuildingLibrary ?
//					GetLibArguments(LinkEnvironment) :
//					GetLinkArguments(LinkEnvironment)
//				);
            ReponseLines.Add(GetLinkArguments(LinkEnvironment));

            // Add the input files to a response file, and pass the response file on the command-line.
            foreach (FileItem InputFile in LinkEnvironment.InputFiles)
            {
                //System.Console.WriteLine("File  {0} ", InputFile.AbsolutePath);
                ReponseLines.Add(string.Format(" \"{0}\"", InputFile.AbsolutePath));
                LinkAction.PrerequisiteItems.Add(InputFile);
            }

            if (!LinkEnvironment.bIsBuildingLibrary)
            {
                // Make sure ThirdParty libs are at the end.
                List <string> ThirdParty = (from Lib in LinkEnvironment.AdditionalLibraries
                                            where Lib.Contains("ThirdParty")
                                            select Lib).ToList();

                LinkEnvironment.AdditionalLibraries.RemoveAll(Element => Element.Contains("ThirdParty"));
                LinkEnvironment.AdditionalLibraries.AddRange(ThirdParty);

                foreach (string InputFile in LinkEnvironment.AdditionalLibraries)
                {
                    FileItem Item = FileItem.GetItemByPath(InputFile);

                    if (Item.AbsolutePath.Contains(".lib"))
                    {
                        continue;
                    }

                    if (Item.ToString().EndsWith(".js"))
                    {
                        ReponseLines.Add(string.Format(" --js-library \"{0}\"", Item.AbsolutePath));
                    }


                    // WARNING: With --pre-js and --post-js, the order in which these directives are passed to
                    // the compiler is very critical, because that dictates the order in which they are appended.
                    //
                    // Set environment variable [ EMCC_DEBUG=1 ] to see the linker order used in packaging.
                    //     See GetSharedArguments_Global() above to set this environment variable

                    else if (Item.ToString().EndsWith(".jspre"))
                    {
                        ReponseLines.Add(string.Format(" --pre-js \"{0}\"", Item.AbsolutePath));
                    }

                    else if (Item.ToString().EndsWith(".jspost"))
                    {
                        ReponseLines.Add(string.Format(" --post-js \"{0}\"", Item.AbsolutePath));
                    }


                    else
                    {
                        ReponseLines.Add(string.Format(" \"{0}\"", Item.AbsolutePath));
                    }

                    LinkAction.PrerequisiteItems.Add(Item);
                }
            }
            // make the file we will create


            OutputFile = FileItem.GetItemByFileReference(LinkEnvironment.OutputFilePath);
            LinkAction.ProducedItems.Add(OutputFile);
            ReponseLines.Add(string.Format(" -o \"{0}\"", OutputFile.AbsolutePath));

            FileItem OutputLink = FileItem.GetItemByPath(LinkEnvironment.OutputFilePath.FullName.Replace(".js", libExt).Replace(".html", libExt));

            LinkAction.ProducedItems.Add(OutputLink);
            if (!useLLVMwasmBackend)
            {
                ReponseLines.Add(string.Format(" --save-bc \"{0}\"", OutputLink.AbsolutePath));
            }

            LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath);

            FileReference ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile);

            // this is needed when using EMCC_DEBUG_SAVE
            if (!FileReference.Exists(ResponseFileName))
            {
                DirectoryReference.CreateDirectory(ResponseFileName.Directory);
            }
            FileItem ResponseFileItem = FileItem.CreateIntermediateTextFile(ResponseFileName, ReponseLines);

            LinkAction.CommandArguments += string.Format(" @\"{0}\"", ResponseFileName);
            LinkAction.PrerequisiteItems.Add(ResponseFileItem);
            Actions.Add(LinkAction);

            return(OutputFile);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Main entry point
        /// </summary>
        /// <param name="Arguments">Command-line arguments</param>
        /// <returns>One of the values of ECompilationResult</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Parse all the targets being built
            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, bSkipRulesCompile);

            if (TargetDescriptors.Count == 0)
            {
                throw new BuildException("No targets specified to clean");
            }

            // Also add implicit descriptors for cleaning UnrealBuildTool
            if (!BuildConfiguration.bDoNotBuildUHT)
            {
                const string UnrealHeaderToolTarget = "UnrealHeaderTool";

                // Get a list of project files to clean UHT for
                List <FileReference> ProjectFiles = new List <FileReference>();
                foreach (TargetDescriptor TargetDesc in TargetDescriptors)
                {
                    if (TargetDesc.Name != UnrealHeaderToolTarget && !RemoteMac.HandlesTargetPlatform(TargetDesc.Platform))
                    {
                        if (ProjectFiles.Count == 0)
                        {
                            ProjectFiles.Add(null);
                        }
                        if (TargetDesc.ProjectFile != null && !ProjectFiles.Contains(TargetDesc.ProjectFile))
                        {
                            ProjectFiles.Add(TargetDesc.ProjectFile);
                        }
                    }
                }

                // Add descriptors for cleaning UHT with all these projects
                if (ProjectFiles.Count > 0)
                {
                    UnrealTargetConfiguration Configuration = BuildConfiguration.bForceDebugUnrealHeaderTool ? UnrealTargetConfiguration.Debug : UnrealTargetConfiguration.Development;
                    string Architecture = UEBuildPlatform.GetBuildPlatform(BuildHostPlatform.Current.Platform).GetDefaultArchitecture(null);
                    foreach (FileReference ProjectFile in ProjectFiles)
                    {
                        TargetDescriptors.Add(new TargetDescriptor(ProjectFile, UnrealHeaderToolTarget, BuildHostPlatform.Current.Platform, Configuration, Architecture, null));
                    }
                }
            }

            // Output the list of targets that we're cleaning
            Log.TraceInformation("Cleaning {0} binaries...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct()));

            // Loop through all the targets, and clean them all
            HashSet <FileReference>      FilesToDelete       = new HashSet <FileReference>();
            HashSet <DirectoryReference> DirectoriesToDelete = new HashSet <DirectoryReference>();

            foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
            {
                // Create the rules assembly
                RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDescriptor.ProjectFile, TargetDescriptor.Name, bSkipRulesCompile, BuildConfiguration.bUsePrecompiled, TargetDescriptor.ForeignPlugin);

                // Create the rules object
                ReadOnlyTargetRules Target = new ReadOnlyTargetRules(RulesAssembly.CreateTargetRules(TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, TargetDescriptor.Architecture, TargetDescriptor.ProjectFile, TargetDescriptor.AdditionalArguments));

                // Find the base folders that can contain binaries
                List <DirectoryReference> BaseDirs = new List <DirectoryReference>();
                BaseDirs.Add(UnrealBuildTool.EngineDirectory);
                BaseDirs.Add(UnrealBuildTool.EnterpriseDirectory);
                foreach (FileReference Plugin in Plugins.EnumeratePlugins(Target.ProjectFile))
                {
                    BaseDirs.Add(Plugin.Directory);
                }
                if (Target.ProjectFile != null)
                {
                    BaseDirs.Add(Target.ProjectFile.Directory);
                }

                // If we're running a precompiled build, remove anything under the engine folder
                BaseDirs.RemoveAll(x => RulesAssembly.IsReadOnly(x));

                // Get all the names which can prefix build products
                List <string> NamePrefixes = new List <string>();
                if (Target.Type != TargetType.Program)
                {
                    NamePrefixes.Add(UEBuildTarget.GetAppNameForTargetType(Target.Type));
                }
                NamePrefixes.Add(Target.Name);

                // Get the suffixes for this configuration
                List <string> NameSuffixes = new List <string>();
                if (Target.Configuration == Target.UndecoratedConfiguration)
                {
                    NameSuffixes.Add("");
                }
                NameSuffixes.Add(String.Format("-{0}-{1}", Target.Platform.ToString(), Target.Configuration.ToString()));
                if (!String.IsNullOrEmpty(Target.Architecture))
                {
                    NameSuffixes.AddRange(NameSuffixes.ToArray().Select(x => x + Target.Architecture));
                }

                // Add all the makefiles and caches to be deleted
                FilesToDelete.Add(TargetMakefile.GetLocation(Target.ProjectFile, Target.Name, Target.Platform, Target.Configuration));
                FilesToDelete.UnionWith(SourceFileMetadataCache.GetFilesToClean(Target.ProjectFile));
                FilesToDelete.UnionWith(ActionHistory.GetFilesToClean(Target.ProjectFile, Target.Name, Target.Platform, Target.Type, Target.Architecture));

                // Add all the intermediate folders to be deleted
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    foreach (string NamePrefix in NamePrefixes)
                    {
                        DirectoryReference GeneratedCodeDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, "Inc");
                        if (DirectoryReference.Exists(GeneratedCodeDir))
                        {
                            DirectoriesToDelete.Add(GeneratedCodeDir);
                        }

                        DirectoryReference IntermediateDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, Target.Configuration.ToString());
                        if (DirectoryReference.Exists(IntermediateDir))
                        {
                            DirectoriesToDelete.Add(IntermediateDir);
                        }
                    }
                }

                // List of additional files and directories to clean, specified by the target platform
                List <FileReference>      AdditionalFilesToDelete       = new List <FileReference>();
                List <DirectoryReference> AdditionalDirectoriesToDelete = new List <DirectoryReference>();

                // Add all the build products from this target
                string[] NamePrefixesArray = NamePrefixes.Distinct().ToArray();
                string[] NameSuffixesArray = NameSuffixes.Distinct().ToArray();
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    DirectoryReference BinariesDir = DirectoryReference.Combine(BaseDir, "Binaries", Target.Platform.ToString());
                    if (DirectoryReference.Exists(BinariesDir))
                    {
                        UEBuildPlatform.GetBuildPlatform(Target.Platform).FindBuildProductsToClean(BinariesDir, NamePrefixesArray, NameSuffixesArray, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);
                    }
                }

                // Get all the additional intermediate folders created by this platform
                UEBuildPlatform.GetBuildPlatform(Target.Platform).FindAdditionalBuildProductsToClean(Target, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);

                // Add the platform's files and directories to the main list
                FilesToDelete.UnionWith(AdditionalFilesToDelete);
                DirectoriesToDelete.UnionWith(AdditionalDirectoriesToDelete);
            }

            // Delete all the directories, then all the files. By sorting the list of directories before we delete them, we avoid spamming the log if a parent directory is deleted first.
            foreach (DirectoryReference DirectoryToDelete in DirectoriesToDelete.OrderBy(x => x.FullName))
            {
                if (DirectoryReference.Exists(DirectoryToDelete))
                {
                    Log.TraceVerbose("    Deleting {0}{1}...", DirectoryToDelete, Path.DirectorySeparatorChar);
                    try
                    {
                        DirectoryReference.Delete(DirectoryToDelete, true);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", DirectoryToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            foreach (FileReference FileToDelete in FilesToDelete.OrderBy(x => x.FullName))
            {
                if (FileReference.Exists(FileToDelete))
                {
                    Log.TraceVerbose("    Deleting " + FileToDelete);
                    try
                    {
                        FileReference.Delete(FileToDelete);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", FileToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            // Also clean all the remote targets
            for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++)
            {
                TargetDescriptor TargetDescriptor = TargetDescriptors[Idx];
                if (RemoteMac.HandlesTargetPlatform(TargetDescriptor.Platform))
                {
                    RemoteMac RemoteMac = new RemoteMac(TargetDescriptor.ProjectFile);
                    RemoteMac.Clean(TargetDescriptor);
                }
            }

            return(0);
        }
        public static void WriteDocumentation(Type RulesType, FileReference OutputFile)
        {
            // Get the path to the XML documentation
            FileReference InputDocumentationFile = new FileReference(Assembly.GetExecutingAssembly().Location).ChangeExtension(".xml");

            if (!FileReference.Exists(InputDocumentationFile))
            {
                throw new BuildException("Generated assembly documentation not found at {0}.", InputDocumentationFile);
            }

            // Get the current engine version for versioning the page
            BuildVersion Version;

            if (!BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
            {
                throw new BuildException("Unable to read the current build version");
            }

            // Read the documentation
            XmlDocument InputDocumentation = new XmlDocument();

            InputDocumentation.Load(InputDocumentationFile.FullName);

            // Filter the properties into read-only and read/write lists
            List <FieldInfo> ReadOnlyFields  = new List <FieldInfo>();
            List <FieldInfo> ReadWriteFields = new List <FieldInfo>();

            foreach (FieldInfo Field in RulesType.GetFields(BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public))
            {
                if (!Field.FieldType.IsClass || !Field.FieldType.Name.EndsWith("TargetRules"))
                {
                    if (Field.IsInitOnly)
                    {
                        ReadOnlyFields.Add(Field);
                    }
                    else
                    {
                        ReadWriteFields.Add(Field);
                    }
                }
            }

            // Make sure the output file is writable
            FileReference.MakeWriteable(OutputFile);

            // Generate the UDN documentation file
            using (StreamWriter Writer = new StreamWriter(OutputFile.FullName))
            {
                Writer.WriteLine("Availability: NoPublish");
                Writer.WriteLine("Title: Build Configuration Properties Page");
                Writer.WriteLine("Crumbs:");
                Writer.WriteLine("Description: This is a procedurally generated markdown page.");
                Writer.WriteLine("Version: {0}.{1}", Version.MajorVersion, Version.MinorVersion);
                Writer.WriteLine("");
                if (ReadOnlyFields.Count > 0)
                {
                    Writer.WriteLine("### Read-Only Properties");
                    Writer.WriteLine();
                    foreach (FieldInfo Field in ReadOnlyFields)
                    {
                        OutputField(InputDocumentation, Field, Writer);
                    }
                    Writer.WriteLine();
                }
                if (ReadWriteFields.Count > 0)
                {
                    Writer.WriteLine("### Read/Write Properties");
                    foreach (FieldInfo Field in ReadWriteFields)
                    {
                        OutputField(InputDocumentation, Field, Writer);
                    }
                    Writer.WriteLine("");
                }
            }

            // Success!
            Log.TraceInformation("Written documentation to {0}.", OutputFile);
        }
Ejemplo n.º 13
0
        private bool WriteXcodeWorkspace()
        {
            bool bSuccess = true;

            var WorkspaceDataContent = new StringBuilder();

            WorkspaceDataContent.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("<Workspace" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("   version = \"1.0\">" + ProjectFileGenerator.NewLine);

            System.Action <List <MasterProjectFolder> /* Folders */, string /* Ident */> AddProjectsFunction = null;
            AddProjectsFunction = (FolderList, Ident) =>
            {
                int SchemeIndex = 0;
                foreach (XcodeProjectFolder CurFolder in FolderList)
                {
                    WorkspaceDataContent.Append(Ident + "   <Group" + ProjectFileGenerator.NewLine);
                    WorkspaceDataContent.Append(Ident + "      location = \"container:\"      name = \"" + CurFolder.FolderName + "\">" + ProjectFileGenerator.NewLine);

                    AddProjectsFunction(CurFolder.SubFolders, Ident + "   ");

                    List <ProjectFile> ChildProjects = new List <ProjectFile>(CurFolder.ChildProjects);
                    ChildProjects.Sort((ProjectFile A, ProjectFile B) => { return(A.ProjectFilePath.GetFileName().CompareTo(B.ProjectFilePath.GetFileName())); });

                    foreach (ProjectFile CurProject in ChildProjects)
                    {
                        XcodeProjectFile XcodeProject = CurProject as XcodeProjectFile;
                        if (XcodeProject != null)
                        {
                            WorkspaceDataContent.Append(Ident + "      <FileRef" + ProjectFileGenerator.NewLine);
                            WorkspaceDataContent.Append(Ident + "         location = \"group:" + XcodeProject.ProjectFilePath.MakeRelativeTo(ProjectFileGenerator.MasterProjectPath) + "\">" + ProjectFileGenerator.NewLine);
                            WorkspaceDataContent.Append(Ident + "      </FileRef>" + ProjectFileGenerator.NewLine);

                            // Also, update project's schemes index so that the schemes list order match projects order in the navigator
                            FileReference SchemeManagementFile = XcodeProject.ProjectFilePath + "/xcuserdata/" + Environment.UserName + ".xcuserdatad/xcschemes/xcschememanagement.plist";
                            if (FileReference.Exists(SchemeManagementFile))
                            {
                                string SchemeManagementContent = FileReference.ReadAllText(SchemeManagementFile);
                                SchemeManagementContent = SchemeManagementContent.Replace("<key>orderHint</key>\n\t\t\t<integer>1</integer>", "<key>orderHint</key>\n\t\t\t<integer>" + SchemeIndex.ToString() + "</integer>");
                                FileReference.WriteAllText(SchemeManagementFile, SchemeManagementContent);
                                SchemeIndex++;
                            }
                        }
                    }

                    WorkspaceDataContent.Append(Ident + "   </Group>" + ProjectFileGenerator.NewLine);
                }
            };
            AddProjectsFunction(RootFolder.SubFolders, "");

            WorkspaceDataContent.Append("</Workspace>" + ProjectFileGenerator.NewLine);

            string ProjectName = MasterProjectName;

            if (ProjectFilePlatform != XcodeProjectFilePlatform.All)
            {
                ProjectName += ProjectFilePlatform == XcodeProjectFilePlatform.Mac ? "_Mac" : (ProjectFilePlatform == XcodeProjectFilePlatform.iOS ? "_IOS" : "_TVOS");
            }
            var WorkspaceDataFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/contents.xcworkspacedata";

            bSuccess = WriteFileIfChanged(WorkspaceDataFilePath, WorkspaceDataContent.ToString(), new UTF8Encoding());
            if (bSuccess)
            {
                var WorkspaceSettingsFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/xcuserdata/" + Environment.UserName + ".xcuserdatad/WorkspaceSettings.xcsettings";
                bSuccess = WriteWorkspaceSettingsFile(WorkspaceSettingsFilePath);
            }

            return(bSuccess);
        }
Ejemplo n.º 14
0
        public override CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, ActionGraph ActionGraph)
        {
            VCEnvironment EnvVars = VCEnvironment.SetEnvironment(CppPlatform, Compiler);

            // Get the MSVC arguments required to compile all files in this batch
            List <string> SharedArguments = new List <string>();

            SharedArguments.Add("/nologo");
            SharedArguments.Add("/P");             // Preprocess
            SharedArguments.Add("/C");             // Preserve comments when preprocessing
            SharedArguments.Add("/D PVS_STUDIO");
            SharedArguments.Add("/wd4005");
            foreach (DirectoryReference IncludePath in CompileEnvironment.IncludePaths.UserIncludePaths)
            {
                SharedArguments.Add(String.Format("/I \"{0}\"", IncludePath));
            }
            foreach (DirectoryReference IncludePath in CompileEnvironment.IncludePaths.SystemIncludePaths)
            {
                SharedArguments.Add(String.Format("/I \"{0}\"", IncludePath));
            }
            foreach (string Definition in CompileEnvironment.Definitions)
            {
                SharedArguments.Add(String.Format("/D \"{0}\"", Definition));
            }
            foreach (FileItem ForceIncludeFile in CompileEnvironment.ForceIncludeFiles)
            {
                SharedArguments.Add(String.Format("/FI\"{0}\"", ForceIncludeFile.Location));
            }

            // Get the path to PVS studio
            FileReference AnalyzerFile = new FileReference(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "PVS-Studio", "x64", "PVS-Studio.exe"));

            // Check if AutoSDK is set up and PVS-Studio exists in it.
            bool          UseSavedLicense  = false;
            FileReference EnginePVS        = FileReference.Combine(UnrealBuildTool.RootDirectory, "Engine", "Extras", "ThirdPartyNotUE", "NoRedist", "PVS-Studio", "PVS-Studio.exe");
            FileReference EnginePVSLicense = FileReference.Combine(UnrealBuildTool.RootDirectory, "Engine", "Extras", "ThirdPartyNotUE", "NoRedist", "PVS-Studio", "PVS-Studio.lic");

            if (FileReference.Exists(EnginePVS))
            {
                if (FileReference.Exists(EnginePVSLicense))
                {
                    UseSavedLicense = true;
                }
                AnalyzerFile = EnginePVS;
            }

            if (!FileReference.Exists(AnalyzerFile))
            {
                throw new BuildException("Unable to find PVS-Studio at {0}", AnalyzerFile);
            }

            CPPOutput Result = new CPPOutput();

            foreach (FileItem SourceFile in InputFiles)
            {
                // Get the file names for everything we need
                string BaseFileName = SourceFile.Location.GetFileName();

                // Write the response file
                FileReference PreprocessedFileLocation = FileReference.Combine(OutputDir, BaseFileName + ".i");

                List <string> Arguments = new List <string>(SharedArguments);
                Arguments.Add(String.Format("/Fi\"{0}\"", PreprocessedFileLocation));                 // Preprocess to a file
                Arguments.Add(String.Format("\"{0}\"", SourceFile.AbsolutePath));

                FileReference ResponseFileLocation = FileReference.Combine(OutputDir, BaseFileName + ".i.response");
                FileItem      ResponseFileItem     = FileItem.CreateIntermediateTextFile(ResponseFileLocation, String.Join("\n", Arguments));

                // Preprocess the source file
                FileItem PreprocessedFileItem = FileItem.GetItemByFileReference(PreprocessedFileLocation);

                Action PreprocessAction = ActionGraph.Add(ActionType.Compile);
                PreprocessAction.CommandPath      = EnvVars.CompilerPath.FullName;
                PreprocessAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
                PreprocessAction.CommandArguments = " @\"" + ResponseFileItem.AbsolutePath + "\"";
                PreprocessAction.PrerequisiteItems.AddRange(CompileEnvironment.ForceIncludeFiles);
                PreprocessAction.PrerequisiteItems.Add(SourceFile);
                PreprocessAction.PrerequisiteItems.Add(ResponseFileItem);
                PreprocessAction.ProducedItems.Add(PreprocessedFileItem);
                PreprocessAction.bShouldOutputStatusDescription = false;

                // Write the PVS studio config file
                StringBuilder ConfigFileContents = new StringBuilder();
                ConfigFileContents.AppendFormat("exclude-path={0}\n", EnvVars.VCInstallDir.FullName);
                if (CppPlatform == CppPlatform.Win64)
                {
                    ConfigFileContents.Append("platform=x64\n");
                }
                else if (CppPlatform == CppPlatform.Win32)
                {
                    ConfigFileContents.Append("platform=Win32\n");
                }
                else
                {
                    throw new BuildException("PVS studio does not support this platform");
                }
                ConfigFileContents.Append("preprocessor=visualcpp\n");
                ConfigFileContents.Append("language=C++\n");
                ConfigFileContents.Append("skip-cl-exe=yes\n");
                ConfigFileContents.AppendFormat("i-file={0}\n", PreprocessedFileItem.Location.FullName);

                FileReference ConfigFileLocation = FileReference.Combine(OutputDir, BaseFileName + ".cfg");
                FileItem      ConfigFileItem     = FileItem.CreateIntermediateTextFile(ConfigFileLocation, ConfigFileContents.ToString());

                // Run the analzyer on the preprocessed source file
                FileReference OutputFileLocation = FileReference.Combine(OutputDir, BaseFileName + ".pvslog");
                FileItem      OutputFileItem     = FileItem.GetItemByFileReference(OutputFileLocation);

                Action AnalyzeAction = ActionGraph.Add(ActionType.Compile);
                AnalyzeAction.CommandDescription = "Analyzing";
                AnalyzeAction.StatusDescription  = BaseFileName;
                AnalyzeAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory.FullName;
                AnalyzeAction.CommandPath        = AnalyzerFile.FullName;
                AnalyzeAction.CommandArguments   = String.Format("--cl-params \"{0}\" --source-file \"{1}\" --output-file \"{2}\" --cfg \"{3}\" --analysis-mode 4 {4}", PreprocessAction.CommandArguments, SourceFile.AbsolutePath, OutputFileLocation, ConfigFileItem.AbsolutePath, (UseSavedLicense ? string.Format("--lic-file \"{0}\"", EnginePVSLicense.FullName) : string.Empty));
                AnalyzeAction.PrerequisiteItems.Add(ConfigFileItem);
                AnalyzeAction.PrerequisiteItems.Add(PreprocessedFileItem);
                AnalyzeAction.ProducedItems.Add(OutputFileItem);
                AnalyzeAction.bShouldDeleteProducedItems = true;                 // PVS Studio will append by default, so need to delete produced items

                Result.ObjectFiles.AddRange(AnalyzeAction.ProducedItems);
            }
            return(Result);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Attempts to read a previous block of config values from disk
        /// </summary>
        /// <param name="Location">The file to read from</param>
        /// <param name="Types">Array of valid types. Used to resolve serialized type names to concrete types.</param>
        /// <param name="Data">On success, receives the parsed data</param>
        /// <returns>True if the data was read and is valid</returns>
        public static bool TryRead(FileReference Location, IEnumerable <Type> Types, out XmlConfigData Data)
        {
            // Check the file exists first
            if (!FileReference.Exists(Location))
            {
                Data = null;
                return(false);
            }

            // Read the cache from disk
            using (BinaryReader Reader = new BinaryReader(File.Open(Location.FullName, FileMode.Open, FileAccess.Read, FileShare.None)))
            {
                // Check the serialization version matches
                if (Reader.ReadInt32() != SerializationVersion)
                {
                    Data = null;
                    return(false);
                }

                // Read the input files
                FileReference[] InputFiles = Reader.ReadArray(x => x.ReadFileReference());

                // Read the types
                int NumTypes = Reader.ReadInt32();
                Dictionary <Type, KeyValuePair <FieldInfo, object>[]> TypeToValues = new Dictionary <Type, KeyValuePair <FieldInfo, object>[]>(NumTypes);
                for (int TypeIdx = 0; TypeIdx < NumTypes; TypeIdx++)
                {
                    // Read the type name
                    string TypeName = Reader.ReadString();

                    // Try to find it in the list of configurable types
                    Type Type = Types.FirstOrDefault(x => x.Name == TypeName);
                    if (Type == null)
                    {
                        Data = null;
                        return(false);
                    }

                    // Read all the values
                    KeyValuePair <FieldInfo, object>[] Values = new KeyValuePair <FieldInfo, object> [Reader.ReadInt32()];
                    for (int ValueIdx = 0; ValueIdx < Values.Length; ValueIdx++)
                    {
                        string FieldName = Reader.ReadString();

                        // Find the matching field on the output type
                        FieldInfo Field = Type.GetField(FieldName);
                        if (Field == null || Field.GetCustomAttribute <XmlConfigFileAttribute>() == null)
                        {
                            Data = null;
                            return(false);
                        }

                        // Try to parse the value and add it to the output array
                        object Value = Reader.ReadObject(Field.FieldType);
                        Values[ValueIdx] = new KeyValuePair <FieldInfo, object>(Field, Value);
                    }

                    // Add it to the type map
                    TypeToValues.Add(Type, Values);
                }

                // Return the parsed data
                Data = new XmlConfigData(InputFiles.ToArray(), TypeToValues);
                return(true);
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Gets the path to the tool binaries.
        /// </summary>
        /// <param name="Compiler">The compiler version</param>
        /// <param name="VCToolChainDir">Base directory for the VC toolchain</param>
        /// <param name="Architecture">Target Architecture</param>
        /// <returns>Directory containing the 32-bit toolchain binaries</returns>
        public static DirectoryReference GetVCToolPath(WindowsCompiler Compiler, DirectoryReference VCToolChainDir, WindowsArchitecture Architecture)
        {
            if (Compiler >= WindowsCompiler.VisualStudio2017)
            {
                FileReference NativeCompilerPath = FileReference.Combine(VCToolChainDir, "bin", "HostX64", WindowsExports.GetArchitectureSubpath(Architecture), "cl.exe");
                if (FileReference.Exists(NativeCompilerPath))
                {
                    return(NativeCompilerPath.Directory);
                }

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

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

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

            throw new BuildException("No required compiler toolchain found in {0}", VCToolChainDir);
        }
Ejemplo n.º 17
0
        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");
            }

            IDictionary <MasterProjectFolder, Guid> ProjectFolderGuids = GenerateProjectFolderGuids(RootFolder);

            // 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
                {
                    IEnumerable <MasterProjectFolder> AllSolutionFolders = ProjectFolderGuids.Keys.OrderBy(Folder => Folder.FolderName).ThenBy(Folder => ProjectFolderGuids[Folder]);
                    foreach (MasterProjectFolder CurFolder in AllSolutionFolders)
                    {
                        string FolderGUIDString = ProjectFolderGuids[CurFolder].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(\"{0}\") = \"Visualizers\", \"Visualizers\", \"{{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}}\"", SolutionFolderEntryGUID));
                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);

                                // Override the configuration to build for UBT
                                if (bBuildUBTInDebug && CurProject == UBTProject)
                                {
                                    ProjectContext.ConfigurationName = "Debug";
                                }

                                // 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 (MasterProjectFolder CurFolder in LocalMasterProjectFolders)
                            {
                                string CurFolderGUIDString = ProjectFolderGuids[CurFolder].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 (MasterProjectFolder SubFolder in CurFolder.SubFolders)
                                {
                                    //	e.g. "{BF6FB09F-A2A6-468F-BE6F-DEBE07EAD3EA} = {C43B6BB5-3EF0-4784-B896-4099753BCDA9}"
                                    LocalVCSolutionFileContent.AppendLine("		"+ ProjectFolderGuids[SubFolder].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);
        }
Ejemplo n.º 18
0
        private void AddProjectsForAllTargets(
            PlatformProjectGeneratorCollection PlatformProjectGenerators,
            List <FileReference> AllGames,
            out ProjectFile EngineProject,
            out List <ProjectFile> GameProjects,
            out Dictionary <FileReference, ProjectFile> ProgramProjects)
        {
            // As we're creating project files, we'll also keep track of whether we created an "engine" project and return that if we have one
            EngineProject   = null;
            GameProjects    = new List <ProjectFile>();
            ProgramProjects = new Dictionary <FileReference, ProjectFile>();

            // Find all of the target files.  This will filter out any modules or targets that don't
            // belong to platforms we're generating project files for.
            List <FileReference> AllTargetFiles = DiscoverTargets(AllGames);

            // Sort the targets by name. When we have multiple targets of a given type for a project, we'll use the order to determine which goes in the primary project file (so that client names with a suffix will go into their own project).
            AllTargetFiles = AllTargetFiles.OrderBy(x => x.FullName, StringComparer.OrdinalIgnoreCase).ToList();

            foreach (FileReference TargetFilePath in AllTargetFiles)
            {
                string TargetName = TargetFilePath.GetFileNameWithoutAnyExtensions();

                // Check to see if this is an Engine target.  That is, the target is located under the "Engine" folder
                bool IsEngineTarget           = false;
                bool IsEnterpriseTarget       = false;
                bool WantProjectFileForTarget = true;
                if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
                {
                    // This is an engine target
                    IsEngineTarget = true;

                    if (TargetFilePath.IsUnderDirectory(EngineSourceProgramsDirectory))
                    {
                        WantProjectFileForTarget = IncludeEnginePrograms;
                    }
                    else if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EngineSourceDirectory))
                    {
                        WantProjectFileForTarget = bIncludeEngineSource;
                    }
                }
                else if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EnterpriseSourceDirectory))
                {
                    // This is an enterprise target
                    IsEnterpriseTarget = true;

                    if (TargetFilePath.IsUnderDirectory(EnterpriseSourceProgramsDirectory))
                    {
                        WantProjectFileForTarget = bIncludeEnterpriseSource && IncludeEnginePrograms;
                    }
                    else
                    {
                        WantProjectFileForTarget = bIncludeEnterpriseSource;
                    }
                }

                if (WantProjectFileForTarget)
                {
                    RulesAssembly RulesAssembly;

                    FileReference CheckProjectFile =
                        AllGames.FirstOrDefault(x => TargetFilePath.IsUnderDirectory(x.Directory));
                    if (CheckProjectFile == null)
                    {
                        if (TargetFilePath.IsUnderDirectory(UnrealBuildTool.EnterpriseDirectory))
                        {
                            RulesAssembly = RulesCompiler.CreateEnterpriseRulesAssembly(false, false);
                        }
                        else
                        {
                            RulesAssembly = RulesCompiler.CreateEngineRulesAssembly(false, false);
                        }
                    }
                    else
                    {
                        RulesAssembly = RulesCompiler.CreateProjectRulesAssembly(CheckProjectFile, false, false);
                    }

                    // Create target rules for all of the platforms and configuration combinations that we want to enable support for.
                    // Just use the current platform as we only need to recover the target type and both should be supported for all targets...
                    TargetRules TargetRulesObject = RulesAssembly.CreateTargetRules(TargetName,
                                                                                    BuildHostPlatform.Current.Platform, UnrealTargetConfiguration.Development, "", CheckProjectFile,
                                                                                    null);

                    bool IsProgramTarget = false;

                    DirectoryReference GameFolder = null;
                    string             ProjectFileNameBase;
                    if (TargetRulesObject.Type == TargetType.Program)
                    {
                        IsProgramTarget     = true;
                        ProjectFileNameBase = TargetName;
                    }
                    else if (IsEngineTarget)
                    {
                        ProjectFileNameBase = EngineProjectFileNameBase;
                    }
                    else if (IsEnterpriseTarget)
                    {
                        ProjectFileNameBase = EnterpriseProjectFileNameBase;
                    }
                    else
                    {
                        // Figure out which game project this target belongs to
                        FileReference ProjectInfo = FindGameContainingFile(AllGames, TargetFilePath);
                        if (ProjectInfo == null)
                        {
                            throw new BuildException("Found a non-engine target file (" + TargetFilePath +
                                                     ") that did not exist within any of the known game folders");
                        }

                        GameFolder          = ProjectInfo.Directory;
                        ProjectFileNameBase = ProjectInfo.GetFileNameWithoutExtension();
                    }

                    // Get the suffix to use for this project file. If we have multiple targets of the same type, we'll have to split them out into separate IDE project files.
                    string GeneratedProjectName = TargetRulesObject.GeneratedProjectName;
                    if (GeneratedProjectName == null)
                    {
                        ProjectFile ExistingProjectFile;
                        if (ProjectFileMap.TryGetValue(GetRiderProjectLocation(ProjectFileNameBase), out ExistingProjectFile) &&
                            ExistingProjectFile.ProjectTargets.Any(x => x.TargetRules.Type == TargetRulesObject.Type))
                        {
                            GeneratedProjectName = TargetRulesObject.Name;
                        }
                        else
                        {
                            GeneratedProjectName = ProjectFileNameBase;
                        }
                    }

                    FileReference ProjectFilePath = GetRiderProjectLocation(GeneratedProjectName);
                    if (TargetRulesObject.Type == TargetType.Game || TargetRulesObject.Type == TargetType.Client ||
                        TargetRulesObject.Type == TargetType.Server)
                    {
                        // Allow platforms to generate stub projects here...
                        PlatformProjectGenerators.GenerateGameProjectStubs(
                            InGenerator: this,
                            InTargetName: TargetName,
                            InTargetFilepath: TargetFilePath.FullName,
                            InTargetRules: TargetRulesObject,
                            InPlatforms: SupportedPlatforms,
                            InConfigurations: SupportedConfigurations);
                    }

                    DirectoryReference BaseFolder;
                    if (IsProgramTarget)
                    {
                        BaseFolder = TargetFilePath.Directory;
                    }
                    else if (IsEngineTarget)
                    {
                        BaseFolder = UnrealBuildTool.EngineDirectory;
                    }
                    else if (IsEnterpriseTarget)
                    {
                        BaseFolder = UnrealBuildTool.EnterpriseDirectory;
                    }
                    else
                    {
                        BaseFolder = GameFolder;
                    }

                    bool        bProjectAlreadyExisted;
                    ProjectFile ProjectFile = FindOrAddProject(ProjectFilePath, BaseFolder,
                                                               true, out bProjectAlreadyExisted);
                    ProjectFile.IsForeignProject =
                        CheckProjectFile != null && !NativeProjects.IsNativeProject(CheckProjectFile);
                    ProjectFile.IsGeneratedProject = true;
                    ProjectFile.IsStubProject      = UnrealBuildTool.IsProjectInstalled();
                    if (TargetRulesObject.bBuildInSolutionByDefault.HasValue)
                    {
                        ProjectFile.ShouldBuildByDefaultForSolutionTargets =
                            TargetRulesObject.bBuildInSolutionByDefault.Value;
                    }

                    // Add the project to the right output list
                    if (IsProgramTarget)
                    {
                        ProgramProjects[TargetFilePath] = ProjectFile;
                    }
                    else if (IsEngineTarget)
                    {
                        EngineProject = ProjectFile;
                        if (UnrealBuildTool.IsEngineInstalled())
                        {
                            // Allow engine projects to be created but not built for Installed Engine builds
                            EngineProject.IsForeignProject   = false;
                            EngineProject.IsGeneratedProject = true;
                            EngineProject.IsStubProject      = true;
                        }
                    }
                    else if (IsEnterpriseTarget)
                    {
                        ProjectFile EnterpriseProject = ProjectFile;
                        if (UnrealBuildTool.IsEnterpriseInstalled())
                        {
                            // Allow enterprise projects to be created but not built for Installed Engine builds
                            EnterpriseProject.IsForeignProject   = false;
                            EnterpriseProject.IsGeneratedProject = true;
                            EnterpriseProject.IsStubProject      = true;
                        }
                    }
                    else
                    {
                        if (!bProjectAlreadyExisted)
                        {
                            GameProjects.Add(ProjectFile);

                            // Add the .uproject file for this game/template
                            FileReference UProjectFilePath =
                                FileReference.Combine(BaseFolder, ProjectFileNameBase + ".uproject");
                            if (FileReference.Exists(UProjectFilePath))
                            {
                                ProjectFile.AddFileToProject(UProjectFilePath, BaseFolder);
                            }
                            else
                            {
                                throw new BuildException(
                                          "Not expecting to find a game with no .uproject file.  File '{0}' doesn't exist",
                                          UProjectFilePath);
                            }
                        }
                    }

                    foreach (ProjectTarget ExistingProjectTarget in ProjectFile.ProjectTargets)
                    {
                        if (ExistingProjectTarget.TargetRules.Type == TargetRulesObject.Type)
                        {
                            throw new BuildException(
                                      "Not expecting project {0} to already have a target rules of with configuration name {1} ({2}) while trying to add: {3}",
                                      ProjectFilePath, TargetRulesObject.Type.ToString(),
                                      ExistingProjectTarget.TargetRules.ToString(), TargetRulesObject.ToString());
                        }

                        // Not expecting to have both a game and a program in the same project.  These would alias because we share the project and solution configuration names (just because it makes sense to)
                        if ((ExistingProjectTarget.TargetRules.Type == TargetType.Game &&
                             TargetRulesObject.Type == TargetType.Program) ||
                            (ExistingProjectTarget.TargetRules.Type == TargetType.Program &&
                             TargetRulesObject.Type == TargetType.Game))
                        {
                            throw new BuildException(
                                      "Not expecting project {0} to already have a Game/Program target ({1}) associated with it while trying to add: {2}",
                                      ProjectFilePath, ExistingProjectTarget.TargetRules.ToString(),
                                      TargetRulesObject.ToString());
                        }
                    }

                    ProjectTarget ProjectTarget = new ProjectTarget()
                    {
                        TargetRules           = TargetRulesObject,
                        TargetFilePath        = TargetFilePath,
                        ProjectFilePath       = ProjectFilePath,
                        UnrealProjectFilePath = CheckProjectFile,
                        SupportedPlatforms    = TargetRulesObject.GetSupportedPlatforms()
                                                .Where(x => UEBuildPlatform.GetBuildPlatform(x, true) != null).ToArray(),
                        CreateRulesDelegate = (Platform, Configuration) =>
                                              RulesAssembly.CreateTargetRules(TargetName, Platform, Configuration, "", CheckProjectFile,
                                                                              null)
                    };

                    ProjectFile.ProjectTargets.Add(ProjectTarget);

                    // Make sure the *.Target.cs file is in the project.
                    ProjectFile.AddFileToProject(TargetFilePath, BaseFolder);

                    Log.TraceVerbose("Generating target {0} for {1}", TargetRulesObject.Type.ToString(),
                                     ProjectFilePath);
                }
            }
        }
        /// <summary>
        /// Initialize the config system with the given types
        /// </summary>
        public static bool ReadConfigFiles()
        {
            // Find all the configurable types
            List <Type> ConfigTypes = FindConfigurableTypes();

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

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

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

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

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

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

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

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

            // Apply all the static field values
            foreach (KeyValuePair <Type, KeyValuePair <FieldInfo, object>[]> TypeValuesPair in Values.TypeToValues)
            {
                foreach (KeyValuePair <FieldInfo, object> FieldValuePair in TypeValuesPair.Value)
                {
                    if (FieldValuePair.Key.IsStatic)
                    {
                        object Value = InstanceValue(FieldValuePair.Value, FieldValuePair.Key.FieldType);
                        FieldValuePair.Key.SetValue(null, Value);
                    }
                }
            }
            return(true);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Execute the command, having obtained the appropriate mutex
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        private int ExecuteInternal(CommandLineArguments Arguments)
        {
            // Read the target info
            WriteMetadataTargetInfo TargetInfo = BinaryFormatterUtils.Load <WriteMetadataTargetInfo>(Arguments.GetFileReference("-Input="));
            bool bNoManifestChanges            = Arguments.HasOption("-NoManifestChanges");
            int  VersionNumber = Arguments.GetInteger("-Version=");

            Arguments.CheckAllArgumentsUsed();

            // Make sure the version number is correct
            if (VersionNumber != CurrentVersionNumber)
            {
                throw new BuildException("Version number to WriteMetadataMode is incorrect (expected {0}, got {1})", CurrentVersionNumber, VersionNumber);
            }

            // Check if we need to set a build id
            TargetReceipt Receipt = TargetInfo.Receipt;

            if (Receipt.Version.BuildId == null)
            {
                // Check if there's an exist version file. If it exists, try to merge in any manifests that are valid (and reuse the existing build id)
                BuildVersion PreviousVersion;
                if (TargetInfo.VersionFile != null && BuildVersion.TryRead(TargetInfo.VersionFile, out PreviousVersion))
                {
                    // Check if we can reuse the existing manifests. This prevents unnecessary builds when switching between projects.
                    Dictionary <FileReference, ModuleManifest> PreviousFileToManifest = new Dictionary <FileReference, ModuleManifest>();
                    if (TryRecyclingManifests(PreviousVersion.BuildId, TargetInfo.FileToManifest.Keys, PreviousFileToManifest))
                    {
                        // Merge files from the existing manifests with the new ones
                        foreach (KeyValuePair <FileReference, ModuleManifest> Pair in PreviousFileToManifest)
                        {
                            ModuleManifest TargetManifest = TargetInfo.FileToManifest[Pair.Key];
                            MergeManifests(Pair.Value, TargetManifest);
                        }

                        // Update the build id to use the current one
                        Receipt.Version.BuildId = PreviousVersion.BuildId;
                    }
                }

                // If the build id is still not set, generate a new one from a GUID
                if (Receipt.Version.BuildId == null)
                {
                    Receipt.Version.BuildId = Guid.NewGuid().ToString();
                }
            }
            else
            {
                // Read all the manifests and merge them into the new ones, if they have the same build id
                foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
                {
                    ModuleManifest SourceManifest;
                    if (TryReadManifest(Pair.Key, out SourceManifest) && SourceManifest.BuildId == Receipt.Version.BuildId)
                    {
                        MergeManifests(SourceManifest, Pair.Value);
                    }
                }
            }

            // Update the build id in all the manifests, and write them out
            foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
            {
                FileReference ManifestFile = Pair.Key;
                if (!UnrealBuildTool.IsFileInstalled(ManifestFile))
                {
                    ModuleManifest Manifest = Pair.Value;
                    Manifest.BuildId = Receipt.Version.BuildId;

                    if (!FileReference.Exists(ManifestFile))
                    {
                        // If the file doesn't already exist, just write it out
                        DirectoryReference.CreateDirectory(ManifestFile.Directory);
                        Manifest.Write(ManifestFile);
                    }
                    else
                    {
                        // Otherwise write it to a buffer first
                        string OutputText;
                        using (StringWriter Writer = new StringWriter())
                        {
                            Manifest.Write(Writer);
                            OutputText = Writer.ToString();
                        }

                        // And only write it to disk if it's been modified. Note that if a manifest is out of date, we should have generated a new build id causing the contents to differ.
                        string CurrentText = FileReference.ReadAllText(ManifestFile);
                        if (CurrentText != OutputText)
                        {
                            if (bNoManifestChanges)
                            {
                                Log.TraceError("Build modifies {0}. This is not permitted. Before:\n    {1}\nAfter:\n    {2}", ManifestFile, CurrentText.Replace("\n", "\n    "), OutputText.Replace("\n", "\n    "));
                            }
                            else
                            {
                                FileReference.WriteAllText(ManifestFile, OutputText);
                            }
                        }
                    }
                }
            }

            // Write out the version file, if it's changed. Since this file is next to the executable, it may be used by multiple targets, and we should avoid modifying it unless necessary.
            if (TargetInfo.VersionFile != null && !UnrealBuildTool.IsFileInstalled(TargetInfo.VersionFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.VersionFile.Directory);

                StringWriter Writer = new StringWriter();
                Receipt.Version.Write(Writer);

                string Text = Writer.ToString();
                if (!FileReference.Exists(TargetInfo.VersionFile) || File.ReadAllText(TargetInfo.VersionFile.FullName) != Text)
                {
                    File.WriteAllText(TargetInfo.VersionFile.FullName, Text);
                }
            }

            // Write out the receipt
            if (!UnrealBuildTool.IsFileInstalled(TargetInfo.ReceiptFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.ReceiptFile.Directory);
                Receipt.Write(TargetInfo.ReceiptFile);
            }

            return(0);
        }
Ejemplo n.º 21
0
        protected string GetDsymutilPath(out string ExtraOptions, bool bIsForLTOBuild = false)
        {
            FileReference DsymutilLocation = new FileReference("/usr/bin/dsymutil");

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

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

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

            // sanity check
            if (Tokens.Length < 4 || Tokens[3].Contains(".") == false)
            {
                Log.TraceInformationOnce("Unable to parse dsymutil version out of: {0}", DsymutilVersionString);

                bUseInstalledDsymutil = false;
            }
            else
            {
                string[] Versions = Tokens[3].Split(".".ToCharArray());
                if (Versions.Length < 3)
                {
                    Log.TraceInformationOnce("Unable to parse version token: {0}", Tokens[3]);
                }
                else
                {
                    if (!int.TryParse(Versions[0], out Major) || !int.TryParse(Versions[1], out Minor) || !int.TryParse(Versions[2], out Patch))
                    {
                        Log.TraceInformationOnce("Unable to parse version tokens: {0}", Tokens[3]);
                    }
                    else
                    {
                        Log.TraceInformationOnce("Parsed dsymutil version as {0}.{1}.{2}", Major, Minor, Patch);

                        if (Major < 10 || (Minor == 0 && Patch == 0))
                        {
                            bUseInstalledDsymutil = false;
                        }
                    }
                }
            }

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

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

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

            // 10.0.1 has an issue with LTO builds where we need to limit the number of threads
            ExtraOptions = (bIsForLTOBuild && Major == 10 && Minor == 0 && Patch == 1) ? "-j 1" : "";
            return(DsymutilLocation.FullName);
        }