Пример #1
0
        /// <summary>
        /// Initializes environment variables required by toolchain. Different for 32 and 64 bit.
        /// </summary>
        public static VCEnvironment SetEnvironment(CppPlatform Platform, WindowsCompiler Compiler)
        {
            if (EnvVars != null && EnvVars.Platform == Platform)
            {
                return(EnvVars);
            }

            EnvVars = new VCEnvironment(Platform, Compiler);
            return(EnvVars);
        }
Пример #2
0
        /**
         * Initializes environment variables required by toolchain. Different for 32 and 64 bit.
         */
        public static VCEnvironment SetEnvironment(CPPTargetPlatform Platform)
        {
            if (EnvVars != null && EnvVars.Platform == Platform)
            {
                return(EnvVars);
            }

            EnvVars = new VCEnvironment(Platform);
            return(EnvVars);
        }
Пример #3
0
		/// <summary>
		/// Initializes environment variables required by toolchain. Different for 32 and 64 bit.
		/// </summary>
		public static VCEnvironment SetEnvironment(CPPTargetPlatform Platform, bool bSupportWindowsXP)
		{
			if (EnvVars != null && EnvVars.Platform == Platform)
			{
				return EnvVars;
			}

			EnvVars = new VCEnvironment(Platform, bSupportWindowsXP);
			return EnvVars;
		}
Пример #4
0
        /// <summary>
        /// Initializes environment variables required by toolchain. Different for 32 and 64 bit.
        /// </summary>
        public static VCEnvironment SetEnvironment(CPPTargetPlatform Platform, bool bSupportWindowsXP)
        {
            if (EnvVars != null && EnvVars.Platform == Platform)
            {
                return(EnvVars);
            }

            EnvVars = new VCEnvironment(Platform, bSupportWindowsXP);
            return(EnvVars);
        }
Пример #5
0
		/**
		 * Initializes environment variables required by toolchain. Different for 32 and 64 bit.
		 */
		public static VCEnvironment SetEnvironment(CPPTargetPlatform Platform)
		{
			if (EnvVars != null && EnvVars.Platform == Platform)
			{
				return EnvVars;
			}

			EnvVars = new VCEnvironment(Platform);
			return EnvVars;
		}
        public PVSToolChain(ReadOnlyTargetRules Target)
        {
            Platform = Target.Platform;
            EnvVars  = Target.WindowsPlatform.Environment;

            AnalyzerFile = FileReference.Combine(new DirectoryReference(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)), "PVS-Studio", "x64", "PVS-Studio.exe");
            if (!FileReference.Exists(AnalyzerFile))
            {
                FileReference EngineAnalyzerFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "Engine", "Extras", "ThirdPartyNotUE", "NoRedist", "PVS-Studio", "PVS-Studio.exe");
                if (FileReference.Exists(EngineAnalyzerFile))
                {
                    AnalyzerFile = EngineAnalyzerFile;
                }
                else
                {
                    throw new BuildException("Unable to find PVS-Studio at {0} or {1}", AnalyzerFile, EngineAnalyzerFile);
                }
            }

            FileReference SettingsPath = FileReference.Combine(new DirectoryReference(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)), "PVS-Studio", "Settings.xml");

            if (FileReference.Exists(SettingsPath))
            {
                try
                {
                    XmlSerializer Serializer = new XmlSerializer(typeof(PVSApplicationSettings));
                    using (FileStream Stream = new FileStream(SettingsPath.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        ApplicationSettings = (PVSApplicationSettings)Serializer.Deserialize(Stream);
                    }
                }
                catch (Exception Ex)
                {
                    throw new BuildException(Ex, "Unable to read PVS-Studio settings file from {0}", SettingsPath);
                }
            }

            if (ApplicationSettings != null && !String.IsNullOrEmpty(ApplicationSettings.UserName) && !String.IsNullOrEmpty(ApplicationSettings.SerialNumber))
            {
                LicenseFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "PVS", "PVS-Studio.lic");
                FileItem.CreateIntermediateTextFile(LicenseFile, new string[] { ApplicationSettings.UserName, ApplicationSettings.SerialNumber });
            }
            else
            {
                FileReference DefaultLicenseFile = AnalyzerFile.ChangeExtension(".lic");
                if (FileReference.Exists(DefaultLicenseFile))
                {
                    LicenseFile = DefaultLicenseFile;
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Gets the default include paths for the given platform.
        /// </summary>
        public static string GetVCIncludePaths(CPPTargetPlatform Platform)
        {
            Debug.Assert(Platform == CPPTargetPlatform.UWP);

            // Make sure we've got the environment variables set up for this target
            VCEnvironment.SetEnvironment(Platform, false);

            // Also add any include paths from the INCLUDE environment variable.  MSVC is not necessarily running with an environment that
            // matches what UBT extracted from the vcvars*.bat using SetEnvironmentVariablesFromBatchFile().  We'll use the variables we
            // extracted to populate the project file's list of include paths
            // @todo projectfiles: Should we only do this for VC++ platforms?
            var IncludePaths = Environment.GetEnvironmentVariable("INCLUDE");

            if (!String.IsNullOrEmpty(IncludePaths) && !IncludePaths.EndsWith(";"))
            {
                IncludePaths += ";";
            }

            return(IncludePaths);
        }
Пример #8
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            var EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.Config.Target.Platform, false);

            StringBuilder Arguments = new StringBuilder();

            AppendCLArguments_Global(CompileEnvironment, EnvVars, Arguments);

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                string IncludePathRelative = Utils.CleanDirectorySeparators(Utils.MakePathRelativeTo(IncludePath, Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine/Source")), '/');
                Arguments.AppendFormat(" /I \"{0}\"", IncludePathRelative);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                string IncludePathRelative = Utils.CleanDirectorySeparators(Utils.MakePathRelativeTo(IncludePath, Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine/Source")), '/');
                Arguments.AppendFormat(" /I \"{0}\"", IncludePathRelative);
            }


            if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
            {
                // Add .NET framework assembly paths.  This is needed so that C++/CLI projects
                // can reference assemblies with #using, without having to hard code a path in the
                // .cpp file to the assembly's location.
                foreach (string AssemblyPath in CompileEnvironment.Config.SystemDotNetAssemblyPaths)
                {
                    Arguments.AppendFormat(" /AI \"{0}\"", AssemblyPath);
                }

                // Add explicit .NET framework assembly references
                foreach (string AssemblyName in CompileEnvironment.Config.FrameworkAssemblyDependencies)
                {
                    Arguments.AppendFormat(" /FU \"{0}\"", AssemblyName);
                }

                // Add private assembly references
                foreach (PrivateAssemblyInfo CurAssemblyInfo in CompileEnvironment.PrivateAssemblyDependencies)
                {
                    Arguments.AppendFormat(" /FU \"{0}\"", CurAssemblyInfo.FileItem.AbsolutePath);
                }
            }


            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                // Escape all quotation marks so that they get properly passed with the command line.
                var DefinitionArgument = Definition.Contains("\"") ? Definition.Replace("\"", "\\\"") : Definition;
                Arguments.AppendFormat(" /D\"{0}\"", DefinitionArgument);
            }

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

            // Create a compile action for each source file.
            CPPOutput Result = new CPPOutput();

            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";

                StringBuilder FileArguments = new StringBuilder();
                bool          bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

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

                // If this is a CLR file then make sure our dependent assemblies are added as prerequisites
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
                {
                    foreach (PrivateAssemblyInfo CurPrivateAssemblyDependency in CompileEnvironment.PrivateAssemblyDependencies)
                    {
                        CompileAction.PrerequisiteItems.Add(CurPrivateAssemblyDependency.FileItem);
                    }
                }

                bool bEmitsObjectFile = true;
                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Generate a CPP File that just includes the precompiled header.
                    string        PCHCPPFilename = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName() + ".cpp";
                    FileReference PCHCPPPath     = FileReference.Combine(CompileEnvironment.Config.OutputDirectory, PCHCPPFilename);
                    FileItem      PCHCPPFile     = FileItem.CreateIntermediateTextFile(
                        PCHCPPPath,
                        string.Format("#include \"{0}\"\r\n", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename)
                        );

                    // Make sure the original source directory the PCH header file existed in is added as an include
                    // path -- it might be a private PCH header and we need to make sure that its found!
                    string OriginalPCHHeaderDirectory = Path.GetDirectoryName(SourceFile.AbsolutePath);
                    FileArguments.AppendFormat(" /I \"{0}\"", OriginalPCHHeaderDirectory);

                    var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.UWP).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
                    // Add the precompiled header file to the produced items list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByFileReference(
                        FileReference.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments.AppendFormat(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    FileArguments.AppendFormat(" /Fp\"{0}\"", PrecompiledHeaderFile.AbsolutePath);

                    // If we're creating a PCH that will be used to compile source files for a library, we need
                    // the compiled modules to retain a reference to PCH's module, so that debugging information
                    // will be included in the library.  This is also required to avoid linker warning "LNK4206"
                    // when linking an application that uses this library.
                    if (CompileEnvironment.Config.bIsBuildingLibrary)
                    {
                        // NOTE: The symbol name we use here is arbitrary, and all that matters is that it is
                        // unique per PCH module used in our library
                        string FakeUniquePCHSymbolName = CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileNameWithoutExtension();
                        FileArguments.AppendFormat(" /Yl{0}", FakeUniquePCHSymbolName);
                    }

                    FileArguments.AppendFormat(" \"{0}\"", PCHCPPFile.AbsolutePath);

                    CompileAction.StatusDescription = PCHCPPFilename;
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);

                        FileArguments.AppendFormat(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        FileArguments.AppendFormat(" /Fp\"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath);

                        // Is it unsafe to always force inclusion?  Clang is doing it, and .generated.cpp files
                        // won't work otherwise, because they're not located in the context of the module,
                        // so they can't access the module's PCH without an absolute path.
                        //if( CompileEnvironment.Config.bForceIncludePrecompiledHeader )
                        {
                            // Force include the precompiled header file.  This is needed because we may have selected a
                            // precompiled header that is different than the first direct include in the C++ source file, but
                            // we still need to make sure that our precompiled header is the first thing included!
                            FileArguments.AppendFormat(" /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        }
                    }

                    // Add the source file path to the command-line.
                    FileArguments.AppendFormat(" \"{0}\"", SourceFile.AbsolutePath);

                    CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
                }

                if (bEmitsObjectFile)
                {
                    var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.UWP).GetBinaryExtension(UEBuildBinaryType.Object);
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByFileReference(
                        FileReference.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);
                    FileArguments.AppendFormat(" /Fo\"{0}\"", ObjectFile.AbsolutePath);
                }

                // Create PDB files if we were configured to do that.
                //
                // Also, when debug info is off and XGE is enabled, force PDBs, otherwise it will try to share
                // a PDB file, which causes PCH creation to be serial rather than parallel (when debug info is disabled)
                //		--> See https://udn.epicgames.com/lists/showpost.php?id=50619&list=unprog3
                if (BuildConfiguration.bUsePDBFiles ||
                    (BuildConfiguration.bAllowXGE && !CompileEnvironment.Config.bCreateDebugInfo))
                {
                    string PDBFileName;
                    bool   bActionProducesPDB = false;

                    // All files using the same PCH are required to share the same PDB that was used when compiling the PCH
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        PDBFileName = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName();
                    }
                    // Files creating a PCH use a PDB per file.
                    else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                    {
                        PDBFileName        = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName();
                        bActionProducesPDB = true;
                    }
                    // Ungrouped C++ files use a PDB per file.
                    else if (!bIsPlainCFile)
                    {
                        PDBFileName        = Path.GetFileName(SourceFile.AbsolutePath);
                        bActionProducesPDB = true;
                    }
                    // Group all plain C files that doesn't use PCH into the same PDB
                    else
                    {
                        PDBFileName = "MiscPlainC";
                    }

                    // Specify the PDB file that the compiler should write to.
                    FileItem PDBFile = FileItem.GetItemByFileReference(
                        FileReference.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            PDBFileName + ".pdb"
                            )
                        );
                    FileArguments.AppendFormat(" /Fd\"{0}\"", PDBFile.AbsolutePath);

                    // Only use the PDB as an output file if we want PDBs and this particular action is
                    // the one that produces the PDB (as opposed to no debug info, where the above code
                    // is needed, but not the output PDB, or when multiple files share a single PDB, so
                    // only the action that generates it should count it as output directly)
                    if (BuildConfiguration.bUsePDBFiles && bActionProducesPDB)
                    {
                        CompileAction.ProducedItems.Add(PDBFile);
                        Result.DebugDataFiles.Add(PDBFile);
                    }
                }

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    AppendCLArguments_C(FileArguments);
                }
                else
                {
                    AppendCLArguments_CPP(CompileEnvironment, FileArguments);
                }

                CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
                CompileAction.CommandPath      = EnvVars.CompilerPath;
                CompileAction.CommandArguments = Arguments.ToString() + FileArguments.ToString() + CompileEnvironment.Config.AdditionalArguments;

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    Log.TraceVerbose("Creating PCH: " + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    Log.TraceVerbose("     Command: " + CompileAction.CommandArguments);
                }
                else
                {
                    Log.TraceVerbose("   Compiling: " + CompileAction.StatusDescription);
                    Log.TraceVerbose("     Command: " + CompileAction.CommandArguments);
                }

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

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

                // @todo: XGE has problems remote compiling C++/CLI files that use .NET Framework 4.0
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
                {
                    CompileAction.bCanExecuteRemotely = false;
                }
            }
            return(Result);
        }
Пример #9
0
        static void AppendCLArguments_Global(CPPEnvironment CompileEnvironment, VCEnvironment EnvVars, StringBuilder Arguments)
        {
            //Arguments.Append(" /showIncludes");

            if (BuildConfiguration.bEnableCodeAnalysis)
            {
                Arguments.Append(" /analyze");

                // Don't cause analyze warnings to be errors
                Arguments.Append(" /analyze:WX-");

                // Report functions that use a LOT of stack space.  You can lower this value if you
                // want more aggressive checking for functions that use a lot of stack memory.
                Arguments.Append(" /analyze:stacksize81940");

                // Don't bother generating code, only analyze code (may report fewer warnings though.)
                //Arguments.Append(" /analyze:only");
            }

            // Prevents the compiler from displaying its logo for each invocation.
            Arguments.Append(" /nologo");

            // Enable intrinsic functions.
            Arguments.Append(" /Oi");

            // Pack struct members on 8-byte boundaries.
            Arguments.Append(" /Zp8");

            // Separate functions for linker.
            Arguments.Append(" /Gy");

            // Relaxes floating point precision semantics to allow more optimization.
            Arguments.Append(" /fp:fast");

            // Compile into an .obj file, and skip linking.
            Arguments.Append(" /c");

            // Allow 800% of the default memory allocation limit.
            Arguments.Append(" /Zm800");

            // Allow large object files to avoid hitting the 2^16 section limit when running with -StressTestUnity.
            Arguments.Append(" /bigobj");

            // Disable "The file contains a character that cannot be represented in the current code page" warning for non-US windows.
            Arguments.Append(" /wd4819");

            // @todo UWP: Disable "unreachable code" warning since auto-included vccorlib.h triggers it
            Arguments.Append(" /wd4702");

            // @todo UWP: Silence the hash_map deprecation errors for now. This should be replaced with unordered_map for the real fix.
            if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
            {
                Arguments.Append(" /D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS");
            }

            if (BuildConfiguration.bUseSharedPCHs)
            {
                // @todo SharedPCH: Disable warning about PCH defines not matching .cpp defines.  We "cheat" these defines a little
                // bit to make shared PCHs work.  But it's totally safe.  Trust us.
                Arguments.Append(" /wd4651");

                // @todo SharedPCH: Disable warning about redefining *API macros.  The PCH header is compiled with various DLLIMPORTs, but
                // when a module that uses that PCH header *IS* one of those imports, that module is compiled with EXPORTS, so the macro
                // is redefined on the command-line.  We need to clobber those defines to make shared PCHs work properly!
                Arguments.Append(" /wd4005");
            }

            // If compiling as a DLL, set the relevant defines
            if (CompileEnvironment.Config.bIsBuildingDLL)
            {
                Arguments.Append(" /D_WINDLL");
            }

            // Handle Common Language Runtime support (C++/CLI)
            if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
            {
                Arguments.Append(" /clr");

                // Don't use default lib path, we override it explicitly to use the 4.0 reference assemblies.
                Arguments.Append(" /clr:nostdlib");
            }

            //
            //	Debug
            //
            if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
            {
                // Disable compiler optimization.
                Arguments.Append(" /Od");

                // Favor code size (especially useful for embedded platforms).
                Arguments.Append(" /Os");

                // Allow inline method expansion unless E&C support is requested
                if (!BuildConfiguration.bSupportEditAndContinue)
                {
                    // @todo UWP: No inlining in Debug builds except in the editor where DLL exports/imports aren't handled properly in module _API macros.
                    if (UEBuildConfiguration.bBuildEditor)
                    {
                        Arguments.Append(" /Ob2");
                    }
                }

                // Runtime stack checks are not allowed when compiling for CLR
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
                {
                    Arguments.Append(" /RTCs");
                }
            }
            //
            //	Development and LTCG
            //
            else
            {
                // Maximum optimizations if desired.
                if (CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds)
                {
                    Arguments.Append(" /Ox");

                    // Allow optimized code to be debugged more easily.  This makes PDBs a bit larger, but doesn't noticeably affect
                    // compile times.  The executable code is not affected at all by this switch, only the debugging information.
                    Arguments.Append(" /Zo");
                }

                // Favor code speed.
                Arguments.Append(" /Ot");

                // Only omit frame pointers on the PC (which is implied by /Ox) if wanted.
                if (BuildConfiguration.bOmitFramePointers == false &&
                    (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.UWP))
                {
                    Arguments.Append(" /Oy-");
                }

                // Allow inline method expansion
                Arguments.Append(" /Ob2");

                //
                // LTCG
                //
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
                {
                    if (BuildConfiguration.bAllowLTCG)
                    {
                        // Enable link-time code generation.
                        Arguments.Append(" /GL");
                    }
                }
            }

            //
            //	PC
            //

            // Prompt the user before reporting internal errors to Microsoft.
            Arguments.Append(" /errorReport:prompt");

            // Enable C++ exception handling, but not C exceptions.
            Arguments.Append(" /EHsc");

            // If enabled, create debug information.
            if (CompileEnvironment.Config.bCreateDebugInfo)
            {
                // Store debug info in .pdb files.
                if (BuildConfiguration.bUsePDBFiles)
                {
                    // Create debug info suitable for E&C if wanted.
                    if (BuildConfiguration.bSupportEditAndContinue &&
                        // We only need to do this in debug as that's the only configuration that supports E&C.
                        CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
                    {
                        Arguments.Append(" /ZI");
                    }
                    // Regular PDB debug information.
                    else
                    {
                        Arguments.Append(" /Zi");
                    }
                    // We need to add this so VS won't lock the PDB file and prevent synchronous updates. This forces serialization through MSPDBSRV.exe.
                    // See http://msdn.microsoft.com/en-us/library/dn502518.aspx for deeper discussion of /FS switch.
                    if (BuildConfiguration.bUseIncrementalLinking && WindowsPlatform.Compiler >= WindowsCompiler.VisualStudio2013)
                    {
                        Arguments.Append(" /FS");
                    }
                }
                // Store C7-format debug info in the .obj files, which is faster.
                else
                {
                    Arguments.Append(" /Z7");
                }
            }

            // Specify the appropriate runtime library based on the platform and config.
            if (CompileEnvironment.Config.bUseStaticCRT)
            {
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT)
                {
                    Arguments.Append(" /MTd");
                }
                else
                {
                    Arguments.Append(" /MT");
                }
            }
            else
            {
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT)
                {
                    Arguments.Append(" /MDd");
                }
                else
                {
                    Arguments.Append(" /MD");
                }
            }

            if (UWPPlatform.bBuildForStore)
            {
                Arguments.Append(" /D_BUILD_FOR_STORE=1");
            }

            if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
            {
                // @todo UWP: These must be appended to the end of the system include list, lest they override some of the third party sources includes
                if (Directory.Exists(EnvVars.WindowsSDKExtensionDir))
                {
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\ucrt", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\um", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\shared", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\winrt", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                }
            }

            if (CompileEnvironment.Config.bIsBuildingLibrary == false)             // will put in a config option, but for now...
            {
                // Enable Windows Runtime extensions
                Arguments.Append(" /ZW");
                Arguments.Append(" /DUSE_WINRT_MAIN=1");
                // TODO - richiem - this will have to be updated when final layout SDKs are available
                if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015 &&
                    Directory.Exists(Path.Combine(EnvVars.WindowsSDKExtensionDir, "UnionMetadata")))
                {
                    Arguments.AppendFormat(@" /AI""{0}\UnionMetadata""", EnvVars.WindowsSDKExtensionDir);
                    Arguments.AppendFormat(@" /FU""{0}\UnionMetadata\windows.winmd""", EnvVars.WindowsSDKExtensionDir);
                }
                Arguments.AppendFormat(@" /AI""{0}\..\..\VC\vcpackages""", EnvVars.BaseVSToolPath);
                Arguments.AppendFormat(@" /FU""{0}\..\..\VC\vcpackages\platform.winmd""", EnvVars.BaseVSToolPath);
            }
        }
Пример #10
0
 /// <summary>
 /// Gets the path to MSBuild.exe
 /// </summary>
 /// <returns>Path to MSBuild.exe</returns>
 public static string GetMSBuildToolPath()
 {
     return(VCEnvironment.GetMSBuildToolPath());
 }
Пример #11
0
		static void AppendCLArguments_Global(CPPEnvironment CompileEnvironment, VCEnvironment EnvVars, StringBuilder Arguments)
		{
			// @todo UWP: Why do we ever need WinRT headers when building regular Win32?  Is this just needed for the Windows 10 SDK?
			// @todo UWP: These include paths should be added in SetUpEnvironment(), not here.  Do they need to be the last includes or something?
			if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015 && WindowsPlatform.bUseWindowsSDK10)
			{
				if (Directory.Exists(EnvVars.WindowsSDKExtensionDir))
				{
					CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\um", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
					CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\shared", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
					CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\winrt", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
				}
				if (Directory.Exists(EnvVars.NetFxSDKExtensionDir))
				{
					CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\um", EnvVars.NetFxSDKExtensionDir));
				}
			}

			// NOTE: Uncommenting this line will print includes as they are encountered by the preprocessor.  This can help with diagnosing include order problems.
			if( WindowsPlatform.bCompileWithClang && !WindowsPlatform.bUseVCCompilerArgs )
			{ 
				// Arguments.Append( " -H" );
			}
			else
			{
				// Arguments.Append( " /showIncludes" );
			}

			if( WindowsPlatform.bCompileWithClang )
			{ 
				// Arguments.Append( " -###" );	// @todo clang: Print Clang command-lines (instead of outputting compile results!)

				if( !WindowsPlatform.bUseVCCompilerArgs )
				{
					Arguments.Append( " -std=c++11" );
					Arguments.Append( " -fdiagnostics-format=msvc" );
					Arguments.Append( " -Xclang -relaxed-aliasing -Xclang --dependent-lib=msvcrt -Xclang --dependent-lib=oldnames -gline-tables-only -ffunction-sections" );
				}

				// @todo clang: We're impersonating the Visual C++ compiler by setting MSC_VER and _MSC_FULL_VER to values that MSVC would set
				string VersionString;
				string FullVersionString;
				switch( WindowsPlatform.Compiler )
				{
					case WindowsCompiler.VisualStudio2012:
						VersionString = "17.0";
						FullVersionString = "1700";
						break;
		
					case WindowsCompiler.VisualStudio2013:
						VersionString = "18.0";
						FullVersionString = "1800";
						break;

					case WindowsCompiler.VisualStudio2015:
						VersionString = "19.0";
						FullVersionString = "1900";
						break;

					default:
						throw new BuildException( "Unexpected value for WindowsPlatform.Compiler: " + WindowsPlatform.Compiler.ToString() );
				}

				Arguments.Append(" -fms-compatibility-version=" + VersionString);
				AddDefinition( Arguments, "_MSC_FULL_VER", FullVersionString + "00000" );
			}

			// @todo clang: Clang on Windows doesn't respect "#pragma warning (error: ####)", and we're not passing "/WX", so warnings are not
			// treated as errors when compiling on Windows using Clang right now.


			if( BuildConfiguration.bEnableCodeAnalysis )
			{
				Arguments.Append(" /analyze");

				// Don't cause analyze warnings to be errors
				Arguments.Append(" /analyze:WX-");

				// Report functions that use a LOT of stack space.  You can lower this value if you
				// want more aggressive checking for functions that use a lot of stack memory.
				Arguments.Append(" /analyze:stacksize81940");

				// Don't bother generating code, only analyze code (may report fewer warnings though.)
				//Arguments.Append(" /analyze:only");
			}

			if( WindowsPlatform.bUseVCCompilerArgs )
			{ 
				// Prevents the compiler from displaying its logo for each invocation.
				Arguments.Append(" /nologo");

				// Enable intrinsic functions.
				Arguments.Append(" /Oi");	// @todo clang: No Clang equivalent to this?
			}

			
			if( WindowsPlatform.bCompileWithClang )
			{
				// Tell the Clang compiler whether we want to generate 32-bit code or 64-bit code
				if( CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64 )
				{
					Arguments.Append( " --target=x86_64-pc-windows-msvc" );
				}
				else
				{
					Arguments.Append( " --target=x86-pc-windows-msvc" );
				}
			}

			// Compile into an .obj file, and skip linking.
			if( WindowsPlatform.bUseVCCompilerArgs )
			{
				Arguments.Append(" /c");
			}
			else
			{
				Arguments.Append(" -c");
			}

			if( WindowsPlatform.bUseVCCompilerArgs )
			{
				// Separate functions for linker.
				Arguments.Append(" /Gy");

				// Allow 800% of the default memory allocation limit.
				Arguments.Append(" /Zm800");

				// Disable "The file contains a character that cannot be represented in the current code page" warning for non-US windows.
				Arguments.Append(" /wd4819");
			}

			// @todo UWP: UE4 is non-compliant when it comes to use of %s and %S
			// Previously %s meant "the current character set" and %S meant "the other one".
			// Now %s means multibyte and %S means wide. %Ts means "natural width".
			// Reverting this behaviour until the UE4 source catches up.
			if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
			{
				Arguments.Append(" /D_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1");
			}

			// @todo UWP: Silence the hash_map deprecation errors for now. This should be replaced with unordered_map for the real fix.
			if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
			{
				Arguments.Append(" /D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS");
			}

			if ( BuildConfiguration.bUseSharedPCHs )
			{
				if (WindowsPlatform.bUseVCCompilerArgs)
				{
					// @todo SharedPCH: Disable warning about PCH defines not matching .cpp defines.  We "cheat" these defines a little
					// bit to make shared PCHs work.  But it's totally safe.  Trust us.
					Arguments.Append(" /wd4651");

					// @todo SharedPCH: Disable warning about redefining *API macros.  The PCH header is compiled with various DLLIMPORTs, but
					// when a module that uses that PCH header *IS* one of those imports, that module is compiled with EXPORTS, so the macro
					// is redefined on the command-line.  We need to clobber those defines to make shared PCHs work properly!
					Arguments.Append(" /wd4005");
				}
			}

			// If compiling as a DLL, set the relevant defines
			if (CompileEnvironment.Config.bIsBuildingDLL)
			{
				AddDefinition( Arguments, "_WINDLL" );
			}

			// When targeting Windows XP with Visual Studio 2012+, we need to tell the compiler to use the older Windows SDK that works
			// with Windows XP (http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx)
			if (WindowsPlatform.IsWindowsXPSupported())
			{
				AddDefinition( Arguments, "_USING_V110_SDK71_");
			}


			// Handle Common Language Runtime support (C++/CLI)
			if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
			{
				Arguments.Append(" /clr");

				// Don't use default lib path, we override it explicitly to use the 4.0 reference assemblies.
				Arguments.Append(" /clr:nostdlib");
			}

			//
			//	Debug
			//
			if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
			{
				if( WindowsPlatform.bUseVCCompilerArgs )
				{ 
					// Disable compiler optimization.
					Arguments.Append(" /Od");

					// Favor code size (especially useful for embedded platforms).
					Arguments.Append(" /Os");

					// Allow inline method expansion unless E&C support is requested
					if( !BuildConfiguration.bSupportEditAndContinue )
					{
						Arguments.Append(" /Ob2");
					}

					if ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) || 
						(CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64))
					{
						// Runtime stack checks are not allowed when compiling for CLR
						if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
						{
							Arguments.Append(" /RTCs");
						}
					}
				}
			}
			//
			//	Development and LTCG
			//
			else
			{
				if( WindowsPlatform.bUseVCCompilerArgs )
				{ 
					if(CompileEnvironment.Config.OptimizeCode == ModuleRules.CodeOptimization.InShippingBuildsOnly && CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Shipping)
					{
						// Disable compiler optimization.
						Arguments.Append(" /Od");

						// Favor code size (especially useful for embedded platforms).
						Arguments.Append(" /Os");
					}
					else
					{
						// Maximum optimizations if desired.
						if( CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds )
						{
							Arguments.Append(" /Ox");
						}
				
						// Favor code speed.
						Arguments.Append(" /Ot");

						// Only omit frame pointers on the PC (which is implied by /Ox) if wanted.
						if ( BuildConfiguration.bOmitFramePointers == false
						&& ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) ||
							(CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)))
						{
							Arguments.Append(" /Oy-");
						}
					}

					// Allow inline method expansion
					Arguments.Append(" /Ob2");

					//
					// LTCG
					//
					if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
					{
						if( BuildConfiguration.bAllowLTCG )
						{
							// Enable link-time code generation.
							Arguments.Append(" /GL");
						}
					}
				}
				else
				{
					if(CompileEnvironment.Config.OptimizeCode != ModuleRules.CodeOptimization.InShippingBuildsOnly || CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
					{
						// Maximum optimizations if desired.
						if( CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds )
						{
							Arguments.Append( " -O3");
						}
					}
				}
			}

			//
			//	PC
			//
			if ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) || 
				(CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64))
			{
				// SSE options are not allowed when using CLR compilation
				if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled && WindowsPlatform.bUseVCCompilerArgs)
				{
					if (CompileEnvironment.Config.bUseAVX)
					{
						// Allow the compiler to generate AVX instructions.
						Arguments.Append(" /arch:AVX");
					}
					// SSE options are not allowed when using the 64 bit toolchain
					// (enables SSE2 automatically)
					else if (CompileEnvironment.Config.Target.Platform != CPPTargetPlatform.Win64)
					{
						// Allow the compiler to generate SSE2 instructions.
						Arguments.Append(" /arch:SSE2");
					}
				}

				if( WindowsPlatform.bUseVCCompilerArgs )
				{ 
					// Prompt the user before reporting internal errors to Microsoft.
					Arguments.Append(" /errorReport:prompt");
				}

				if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
				{
					// Enable C++ exceptions when building with the editor or when building UHT.
					if (!WindowsPlatform.bCompileWithClang &&	// @todo clang: C++ exceptions are not supported with Clang on Windows yet
						(CompileEnvironment.Config.bEnableExceptions || UEBuildConfiguration.bBuildEditor || UEBuildConfiguration.bForceEnableExceptions))
					{
						// Enable C++ exception handling, but not C exceptions.
							Arguments.Append(" /EHsc");
						}
					else
					{
						// This is required to disable exception handling in VC platform headers.
						CompileEnvironment.Config.Definitions.Add("_HAS_EXCEPTIONS=0");

						if( !WindowsPlatform.bUseVCCompilerArgs )
						{ 
							Arguments.Append( " -fno-exceptions" );
						}
					}
				}
				else
				{
					// For C++/CLI all exceptions must be left enabled
					Arguments.Append(" /EHa");
				}
			}
			else if (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.HTML5)
			{
				Arguments.Append(" /EHsc"); 
			}

			// If enabled, create debug information.
			if (CompileEnvironment.Config.bCreateDebugInfo)
			{
				if( WindowsPlatform.bUseVCCompilerArgs )
				{ 
					// Store debug info in .pdb files.
					// @todo clang: PDB files are emited from Clang but do not fully work with Visual Studio yet (breakpoints won't hit due to "symbol read error")
					if( BuildConfiguration.bUsePDBFiles )
					{
						// Create debug info suitable for E&C if wanted.
						if( BuildConfiguration.bSupportEditAndContinue &&
							// We only need to do this in debug as that's the only configuration that supports E&C.
							CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
						{
							Arguments.Append(" /ZI");
						}
						// Regular PDB debug information.
						else
						{
							Arguments.Append(" /Zi");
						}
						// We need to add this so VS won't lock the PDB file and prevent synchronous updates. This forces serialization through MSPDBSRV.exe.
						// See http://msdn.microsoft.com/en-us/library/dn502518.aspx for deeper discussion of /FS switch.
						if (BuildConfiguration.bUseIncrementalLinking && WindowsPlatform.Compiler >= WindowsCompiler.VisualStudio2013)
						{
							Arguments.Append(" /FS");
						}
					}
					// Store C7-format debug info in the .obj files, which is faster.
					else
					{
						Arguments.Append(" /Z7");
					}
				}
			}

			// Specify the appropriate runtime library based on the platform and config.
			if( CompileEnvironment.Config.bUseStaticCRT )
			{
				if( CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT )
				{
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /MTd");
					}
					else
					{
						AddDefinition( Arguments, "_MT" );
						AddDefinition( Arguments, "_DEBUG" );
					}
				}
				else
				{
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /MT");
					}
					else
					{
						AddDefinition( Arguments, "_MT" );
					}
				}
			}
			else
			{
				if( CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT )
				{
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /MDd");
					}
					else
					{
						AddDefinition( Arguments, "_MT" );
						AddDefinition( Arguments, "_DEBUG" );
						AddDefinition( Arguments, "_DLL" );
					}
				}
				else
				{
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /MD");
					}
					else
					{
						AddDefinition( Arguments, "_MT" );
						AddDefinition( Arguments, "_DLL" );
					}
				}
			}

			if (WindowsPlatform.bUseVCCompilerArgs && !BuildConfiguration.bRunUnrealCodeAnalyzer)
			{
				// @todo clang: Not supported in clang-cl yet
				if( !WindowsPlatform.bCompileWithClang )
				{
					// Allow large object files to avoid hitting the 2^16 section limit when running with -StressTestUnity.
					Arguments.Append(" /bigobj");

					// Relaxes floating point precision semantics to allow more optimization.
					Arguments.Append(" /fp:fast");
				}

				if (CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds)
				{
					// Allow optimized code to be debugged more easily.  This makes PDBs a bit larger, but doesn't noticeably affect
					// compile times.  The executable code is not affected at all by this switch, only the debugging information.
					if (EnvVars.CLExeVersion >= new Version("18.0.30723"))
					{
						// VC2013 Update 3 has a new flag for doing this
						Arguments.Append(" /Zo");
					}
					else
					{
						Arguments.Append(" /d2Zi+");
					}
				}
			}

			// Disabled when compiling UnrealCodeAnalyzer as it breaks compilation (some structs in clang/llvm headers require 8-byte alignment in 32-bit compilation)
			if (!UnrealBuildTool.CommandLineContains(@"UnrealCodeAnalyzer")
				// and when running UnrealCodeAnalyzer as it doesn't understand the /Zp syntax.
				&& !BuildConfiguration.bRunUnrealCodeAnalyzer)
			{
				if (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)
				{
					// Pack struct members on 8-byte boundaries.
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /Zp8");
					}
					else
					{
						Arguments.Append(" -fpack-struct=8" );
					}
				}
				else
				{
					// Pack struct members on 4-byte boundaries.
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						Arguments.Append(" /Zp4");
					}
					else
					{
						Arguments.Append(" -fpack-struct=4" );
					}
				}
			}

			//
			// Options required by UnrealCodeAnalyzer
			//
			if (BuildConfiguration.bRunUnrealCodeAnalyzer)
			{
				AddDefinition( Arguments, "UNREAL_CODE_ANALYZER");
			}

			//@todo: Disable warnings for VS2015. These should be reenabled as we clear the reasons for them out of the engine source and the VS2015 toolchain evolves.
			if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
			{
				// Disable shadow variable warnings
				Arguments.Append(" /wd4456"); // 4456 - declaration of 'LocalVariable' hides previous local declaration
				Arguments.Append(" /wd4458"); // 4458 - declaration of 'parameter' hides class member
				Arguments.Append(" /wd4459"); // 4459 - declaration of 'LocalVariable' hides global declaration

				Arguments.Append(" /wd4463"); // 4463 - overflow; assigning 1 to bit-field that can only hold values from -1 to 0

				Arguments.Append(" /wd4838"); // 4838: conversion from 'type1' to 'type2' requires a narrowing conversion
			}

		}
Пример #12
0
        static void AppendCLArguments_Global(CPPEnvironment CompileEnvironment, VCEnvironment EnvVars, StringBuilder Arguments)
        {
            //Arguments.Append(" /showIncludes");

            if( BuildConfiguration.bEnableCodeAnalysis )
            {
                Arguments.Append(" /analyze");

                // Don't cause analyze warnings to be errors
                Arguments.Append(" /analyze:WX-");

                // Report functions that use a LOT of stack space.  You can lower this value if you
                // want more aggressive checking for functions that use a lot of stack memory.
                Arguments.Append(" /analyze:stacksize81940");

                // Don't bother generating code, only analyze code (may report fewer warnings though.)
                //Arguments.Append(" /analyze:only");
            }

            // Prevents the compiler from displaying its logo for each invocation.
            Arguments.Append(" /nologo");

            // Enable intrinsic functions.
            Arguments.Append(" /Oi");

            // Pack struct members on 8-byte boundaries.
            Arguments.Append(" /Zp8");

            // Separate functions for linker.
            Arguments.Append(" /Gy");

            // Relaxes floating point precision semantics to allow more optimization.
            Arguments.Append(" /fp:fast");

            // Compile into an .obj file, and skip linking.
            Arguments.Append(" /c");

            // Allow 800% of the default memory allocation limit.
            Arguments.Append(" /Zm800");

            // Allow large object files to avoid hitting the 2^16 section limit when running with -StressTestUnity.
            Arguments.Append(" /bigobj");

            // Disable "The file contains a character that cannot be represented in the current code page" warning for non-US windows.
            Arguments.Append(" /wd4819");

            // @todo UWP: Disable "unreachable code" warning since auto-included vccorlib.h triggers it
            Arguments.Append(" /wd4702");

            // @todo UWP: Silence the hash_map deprecation errors for now. This should be replaced with unordered_map for the real fix.
            if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
            {
                Arguments.Append(" /D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS");
            }

            if ( BuildConfiguration.bUseSharedPCHs )
            {
                // @todo SharedPCH: Disable warning about PCH defines not matching .cpp defines.  We "cheat" these defines a little
                // bit to make shared PCHs work.  But it's totally safe.  Trust us.
                Arguments.Append(" /wd4651");

                // @todo SharedPCH: Disable warning about redefining *API macros.  The PCH header is compiled with various DLLIMPORTs, but
                // when a module that uses that PCH header *IS* one of those imports, that module is compiled with EXPORTS, so the macro
                // is redefined on the command-line.  We need to clobber those defines to make shared PCHs work properly!
                Arguments.Append(" /wd4005");
            }

            // If compiling as a DLL, set the relevant defines
            if (CompileEnvironment.Config.bIsBuildingDLL)
            {
                Arguments.Append(" /D_WINDLL");
            }

            // Handle Common Language Runtime support (C++/CLI)
            if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
            {
                Arguments.Append(" /clr");

                // Don't use default lib path, we override it explicitly to use the 4.0 reference assemblies.
                Arguments.Append(" /clr:nostdlib");
            }

            //
            //	Debug
            //
            if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
            {
                // Disable compiler optimization.
                Arguments.Append(" /Od");

                // Favor code size (especially useful for embedded platforms).
                Arguments.Append(" /Os");

                // Allow inline method expansion unless E&C support is requested
                if( !BuildConfiguration.bSupportEditAndContinue )
                {
                    // @todo UWP: No inlining in Debug builds except in the editor where DLL exports/imports aren't handled properly in module _API macros.
                    if (UEBuildConfiguration.bBuildEditor)
                    {
                        Arguments.Append(" /Ob2");
                    }
                }

                // Runtime stack checks are not allowed when compiling for CLR
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
                {
                    Arguments.Append(" /RTCs");
                }
            }
            //
            //	Development and LTCG
            //
            else
            {
                // Maximum optimizations if desired.
                if (CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds)
                {
                    Arguments.Append(" /Ox");

                    // Allow optimized code to be debugged more easily.  This makes PDBs a bit larger, but doesn't noticeably affect
                    // compile times.  The executable code is not affected at all by this switch, only the debugging information.
                    Arguments.Append(" /Zo");
                }

                // Favor code speed.
                Arguments.Append(" /Ot");

                // Only omit frame pointers on the PC (which is implied by /Ox) if wanted.
                if ( BuildConfiguration.bOmitFramePointers == false
                && (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.UWP))
                {
                    Arguments.Append(" /Oy-");
                }

                // Allow inline method expansion
                Arguments.Append(" /Ob2");

                //
                // LTCG
                //
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
                {
                    if( BuildConfiguration.bAllowLTCG )
                    {
                        // Enable link-time code generation.
                        Arguments.Append(" /GL");
                    }
                }
            }

            //
            //	PC
            //

            // Prompt the user before reporting internal errors to Microsoft.
            Arguments.Append(" /errorReport:prompt");

            // Enable C++ exception handling, but not C exceptions.
            Arguments.Append(" /EHsc");

            // If enabled, create debug information.
            if (CompileEnvironment.Config.bCreateDebugInfo)
            {
                // Store debug info in .pdb files.
                if (BuildConfiguration.bUsePDBFiles)
                {
                    // Create debug info suitable for E&C if wanted.
                    if ( BuildConfiguration.bSupportEditAndContinue &&
                        // We only need to do this in debug as that's the only configuration that supports E&C.
                        CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
                    {
                        Arguments.Append(" /ZI");
                    }
                    // Regular PDB debug information.
                    else
                    {
                        Arguments.Append(" /Zi");
                    }
                    // We need to add this so VS won't lock the PDB file and prevent synchronous updates. This forces serialization through MSPDBSRV.exe.
                    // See http://msdn.microsoft.com/en-us/library/dn502518.aspx for deeper discussion of /FS switch.
                    if (BuildConfiguration.bUseIncrementalLinking && WindowsPlatform.Compiler >= WindowsCompiler.VisualStudio2013)
                    {
                        Arguments.Append(" /FS");
                    }
                }
                // Store C7-format debug info in the .obj files, which is faster.
                else
                {
                    Arguments.Append(" /Z7");
                }
            }

            // Specify the appropriate runtime library based on the platform and config.
            if (CompileEnvironment.Config.bUseStaticCRT)
            {
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT)
                {
                    Arguments.Append(" /MTd");
                }
                else
                {
                    Arguments.Append(" /MT");
                }
            }
            else
            {
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT)
                {
                    Arguments.Append(" /MDd");
                }
                else
                {
                    Arguments.Append(" /MD");
                }
            }

            if (UWPPlatform.bBuildForStore)
            {
                Arguments.Append(" /D_BUILD_FOR_STORE=1");
            }

            if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015)
            {
                // @todo UWP: These must be appended to the end of the system include list, lest they override some of the third party sources includes
                if (Directory.Exists(EnvVars.WindowsSDKExtensionDir))
                {
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\ucrt", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\um", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\shared", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                    CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.Add(string.Format(@"{0}\Include\{1}\winrt", EnvVars.WindowsSDKExtensionDir, EnvVars.WindowsSDKExtensionHeaderLibVersion));
                }
            }

            if (CompileEnvironment.Config.bIsBuildingLibrary == false) // will put in a config option, but for now...
            {
                // Enable Windows Runtime extensions
                Arguments.Append(" /ZW");
                Arguments.Append(" /DUSE_WINRT_MAIN=1");
                // TODO - richiem - this will have to be updated when final layout SDKs are available
                if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2015 &&
                    Directory.Exists(Path.Combine(EnvVars.WindowsSDKExtensionDir, "UnionMetadata")))
                {
                    Arguments.AppendFormat(@" /AI""{0}\UnionMetadata""", EnvVars.WindowsSDKExtensionDir);
                    Arguments.AppendFormat(@" /FU""{0}\UnionMetadata\windows.winmd""", EnvVars.WindowsSDKExtensionDir);
                }
                Arguments.AppendFormat(@" /AI""{0}\..\..\VC\vcpackages""", EnvVars.BaseVSToolPath);
                Arguments.AppendFormat(@" /FU""{0}\..\..\VC\vcpackages\platform.winmd""", EnvVars.BaseVSToolPath);
            }
        }
Пример #13
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));
            }

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

            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.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", PreprocessAction.CommandArguments, SourceFile.AbsolutePath, OutputFileLocation, ConfigFileItem.AbsolutePath);
                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);
        }
Пример #14
0
        /// <summary>
        /// Execute the command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</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 the filter argument
            FileFilter FileFilter = null;

            if (FilterRules.Count > 0)
            {
                FileFilter = new FileFilter(FileFilterType.Exclude);
                foreach (string FilterRule in FilterRules)
                {
                    FileFilter.AddRules(FilterRule.Split(';'));
                }
            }

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

            // Generate the compile DB for each target
            using (ISourceFileWorkingSet WorkingSet = new EmptySourceFileWorkingSet())
            {
                // Find the compile commands for each file in the target
                Dictionary <FileReference, string> FileToCommand = new Dictionary <FileReference, string>();
                foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
                {
                    // Disable PCHs and unity builds for the target
                    TargetDescriptor.AdditionalArguments = TargetDescriptor.AdditionalArguments.Append(new string[] { "-NoPCH", "-DisableUnity" });

                    // Create a makefile for the target
                    UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration.bSkipRulesCompile, BuildConfiguration.bUsePrecompiled);

                    // Find the location of the compiler
                    VCEnvironment Environment = VCEnvironment.Create(WindowsCompiler.Clang, Target.Platform, Target.Rules.WindowsPlatform.Architecture, null, Target.Rules.WindowsPlatform.WindowsSdkVersion, null);
                    FileReference ClangPath   = FileReference.Combine(Environment.CompilerDir, "bin", "clang++.exe");

                    // Convince each module to output its generated code include path
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            Module.bAddGeneratedCodeIncludePath = true;
                        }
                    }

                    // Create all the binaries and modules
                    CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        CppCompileEnvironment BinaryCompileEnvironment = Binary.CreateBinaryCompileEnvironment(GlobalCompileEnvironment);
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            if (!Module.Rules.bUsePrecompiled)
                            {
                                UEBuildModuleCPP.InputFileCollection InputFileCollection = Module.FindInputFiles(Target.Platform, new Dictionary <DirectoryItem, FileItem[]>());

                                List <FileItem> InputFiles = new List <FileItem>();
                                InputFiles.AddRange(InputFileCollection.CPPFiles);
                                InputFiles.AddRange(InputFileCollection.CCFiles);

                                CppCompileEnvironment ModuleCompileEnvironment = Module.CreateModuleCompileEnvironment(Target.Rules, BinaryCompileEnvironment);

                                StringBuilder CommandBuilder = new StringBuilder();
                                CommandBuilder.AppendFormat("\"{0}\"", ClangPath.FullName);
                                foreach (FileItem ForceIncludeFile in ModuleCompileEnvironment.ForceIncludeFiles)
                                {
                                    CommandBuilder.AppendFormat(" -include \"{0}\"", ForceIncludeFile.FullName);
                                }
                                foreach (string Definition in ModuleCompileEnvironment.Definitions)
                                {
                                    CommandBuilder.AppendFormat(" -D\"{0}\"", Definition);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.UserIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.SystemIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }

                                foreach (FileItem InputFile in InputFiles)
                                {
                                    if (FileFilter == null || FileFilter.Matches(InputFile.Location.MakeRelativeTo(UnrealBuildTool.RootDirectory)))
                                    {
                                        FileToCommand[InputFile.Location] = String.Format("{0} \"{1}\"", CommandBuilder, InputFile.FullName);
                                    }
                                }
                            }
                        }
                    }
                }

                // Write the compile database
                FileReference DatabaseFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "compile_commands.json");
                using (JsonWriter Writer = new JsonWriter(DatabaseFile))
                {
                    Writer.WriteArrayStart();
                    foreach (KeyValuePair <FileReference, string> FileCommandPair in FileToCommand.OrderBy(x => x.Key.FullName))
                    {
                        Writer.WriteObjectStart();
                        Writer.WriteValue("file", FileCommandPair.Key.FullName);
                        Writer.WriteValue("command", FileCommandPair.Value);
                        Writer.WriteValue("directory", UnrealBuildTool.EngineSourceDirectory.ToString());
                        Writer.WriteObjectEnd();
                    }
                    Writer.WriteArrayEnd();
                }
            }

            return(0);
        }
Пример #15
0
        private void WriteEnvironmentSetup()
        {
            DirectoryReference VCInstallDir = null;
            string             VCToolPath64 = "";
            VCEnvironment      VCEnv        = null;

            try
            {
                VCEnv = VCEnvironment.Create(WindowsPlatform.GetDefaultCompiler(null), CppPlatform.Win64, null, null);
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to get Visual Studio environment.");
            }

            // Copy environment into a case-insensitive dictionary for easier key lookups
            Dictionary <string, string> envVars = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
            {
                envVars[(string)entry.Key] = (string)entry.Value;
            }

            if (envVars.ContainsKey("CommonProgramFiles"))
            {
                AddText("#import CommonProgramFiles\n");
            }

            if (envVars.ContainsKey("DXSDK_DIR"))
            {
                AddText("#import DXSDK_DIR\n");
            }

            if (envVars.ContainsKey("DurangoXDK"))
            {
                AddText("#import DurangoXDK\n");
            }

            if (VCEnv != null)
            {
                string platformVersionNumber = "VSVersionUnknown";
                platformVersionNumber = "140";


                if (!WindowsPlatform.TryGetVSInstallDir(WindowsPlatform.GetDefaultCompiler(null), out VCInstallDir))
                {
                    string exceptionString = "Error: Cannot locate Visual Studio Installation.";
                    Console.WriteLine(exceptionString);
                    throw new BuildException(exceptionString);
                }

                VCToolPath64 = Environment.GetEnvironmentVariable("VC_COMPILER_DIR");

                AddText(string.Format(".WindowsSDKBasePath = '{0}'\n", VCEnv.WindowsSdkDir));

                AddText("Compiler('UE4ResourceCompiler') \n{\n");
                AddText(string.Format("\t.Executable = '{0}'\n", VCEnv.ResourceCompilerPath));
                AddText("\t.CompilerFamily  = 'custom'\n");
                AddText("}\n\n");


                AddText("Compiler('UE4Compiler') \n{\n");

                AddText(string.Format("\t.Root = '{0}'\n", VCEnv.CompilerPath.Directory));
                AddText("\t.Executable = '$Root$/cl.exe'\n");
                AddText("\t.ExtraFiles =\n\t{\n");
                AddText("\t\t'$Root$/c1.dll'\n");
                AddText("\t\t'$Root$/c1xx.dll'\n");
                AddText("\t\t'$Root$/c2.dll'\n");

                if (File.Exists(FileReference.Combine(VCEnv.CompilerPath.Directory, "1033/clui.dll").ToString()))                 //Check English first...
                {
                    AddText("\t\t'$Root$/1033/clui.dll'\n");
                }
                else
                {
                    var numericDirectories = Directory.GetDirectories(VCToolPath64).Where(d => Path.GetFileName(d).All(char.IsDigit));
                    var cluiDirectories    = numericDirectories.Where(d => Directory.GetFiles(d, "clui.dll").Any());
                    if (cluiDirectories.Any())
                    {
                        AddText(string.Format("\t\t'$Root$/{0}/clui.dll'\n", Path.GetFileName(cluiDirectories.First())));
                    }
                }
                AddText("\t\t'$Root$/mspdbsrv.exe'\n");
                AddText("\t\t'$Root$/mspdbcore.dll'\n");

                AddText(string.Format("\t\t'$Root$/mspft{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msobj{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/mspdb{0}.dll'\n", platformVersionNumber));

                AddText(string.Format("\t\t'{0}/VC/Redist/MSVC/14.21.27702/x64/Microsoft.VC142.CRT/msvcp{1}.dll'\n", VCInstallDir.ToString(), platformVersionNumber));
                AddText(string.Format("\t\t'{0}/VC/Redist/MSVC/14.21.27702/x64/Microsoft.VC142.CRT/vccorlib{1}.dll'\n", VCInstallDir.ToString(), platformVersionNumber));


                AddText("\t}\n");                 //End extra files

                AddText("}\n\n");                 //End compiler
            }

            AddText("Settings \n{\n");

            //Start Environment
            AddText("\t.Environment = \n\t{\n");
            if (VCEnv != null)
            {
                AddText(string.Format("\t\t\"PATH={0}\\Common7\\IDE\\;{1}\",\n", VCInstallDir.ToString(), VCToolPath64));
                if (VCEnv.IncludePaths.Count() > 0)
                {
                    AddText(string.Format("\t\t\"INCLUDE={0}\",\n", String.Join(";", VCEnv.IncludePaths.Select(x => x))));
                }

                if (VCEnv.LibraryPaths.Count() > 0)
                {
                    AddText(string.Format("\t\t\"LIB={0}\",\n", String.Join(";", VCEnv.LibraryPaths.Select(x => x))));
                }
            }
            if (envVars.ContainsKey("TMP"))
            {
                AddText(string.Format("\t\t\"TMP={0}\",\n", envVars["TMP"]));
            }
            if (envVars.ContainsKey("SystemRoot"))
            {
                AddText(string.Format("\t\t\"SystemRoot={0}\",\n", envVars["SystemRoot"]));
            }
            if (envVars.ContainsKey("INCLUDE"))
            {
                AddText(string.Format("\t\t\"INCLUDE={0}\",\n", envVars["INCLUDE"]));
            }
            if (envVars.ContainsKey("LIB"))
            {
                AddText(string.Format("\t\t\"LIB={0}\",\n", envVars["LIB"]));
            }

            AddText("\t}\n");             //End environment
            AddText("}\n\n");             //End Settings
        }
Пример #16
0
        private void WriteEnvironmentSetup()
        {
            VCEnvironment VCEnv = null;

            try
            {
                // This may fail if the caller emptied PATH; we try to ignore the problem since
                // it probably means we are building for another platform.
                if (BuildType == FBBuildType.Windows)
                {
                    VCEnv = VCEnvironment.SetEnvironment(CppPlatform.Win64, WindowsPlatform.GetDefaultCompiler(null));
                }
                else if (BuildType == FBBuildType.XBOne)
                {
                    // If you have XboxOne source access, uncommenting the line below will be better for selecting the appropriate version of the compiler.
                    // Translate the XboxOne compiler to the right Windows compiler to set the VC environment vars correctly...
                    //WindowsCompiler windowsCompiler = XboxOnePlatform.GetDefaultCompiler() == XboxOneCompiler.VisualStudio2015 ? WindowsCompiler.VisualStudio2015 : WindowsCompiler.VisualStudio2017;
                    //VCEnv = VCEnvironment.SetEnvironment(CppPlatform.Win64, windowsCompiler);
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to get Visual Studio environment.");
            }

            // Copy environment into a case-insensitive dictionary for easier key lookups
            Dictionary <string, string> envVars = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
            {
                envVars[(string)entry.Key] = (string)entry.Value;
            }

            if (envVars.ContainsKey("CommonProgramFiles"))
            {
                AddText("#import CommonProgramFiles\n");
            }

            if (envVars.ContainsKey("DXSDK_DIR"))
            {
                AddText("#import DXSDK_DIR\n");
            }

            if (envVars.ContainsKey("DurangoXDK"))
            {
                AddText("#import DurangoXDK\n");
            }

            if (VCEnv != null)
            {
                string platformVersionNumber = "VSVersionUnknown";

                switch (VCEnv.Compiler)
                {
                case WindowsCompiler.VisualStudio2015:
                    platformVersionNumber = "140";
                    break;

                case WindowsCompiler.VisualStudio2017:
                    // For now we are working with the 140 version, might need to change to 141 or 150 depending on the version of the Toolchain you chose
                    // to install
                    platformVersionNumber = "140";
                    break;

                default:
                    string exceptionString = "Error: Unsupported Visual Studio Version.";
                    Console.WriteLine(exceptionString);
                    throw new BuildException(exceptionString);
                }

                AddText(string.Format(".WindowsSDKBasePath = '{0}'\n", VCEnv.WindowsSDKDir));

                AddText("Compiler('UE4ResourceCompiler') \n{\n");
                AddText("\t.Executable = '$WindowsSDKBasePath$/bin/x64/rc.exe'\n");
                AddText("\t.CompilerFamily  = 'custom'\n");
                AddText("}\n\n");


                AddText("Compiler('UE4Compiler') \n{\n");

                AddText(string.Format("\t.Root = '{0}'\n", VCEnv.VCToolPath64));
                AddText("\t.Executable = '$Root$/cl.exe'\n");
                AddText("\t.ExtraFiles =\n\t{\n");
                AddText("\t\t'$Root$/c1.dll'\n");
                AddText("\t\t'$Root$/c1xx.dll'\n");
                AddText("\t\t'$Root$/c2.dll'\n");

                if (File.Exists(VCEnv.VCToolPath64 + "1033/clui.dll")) //Check English first...
                {
                    AddText("\t\t'$Root$/1033/clui.dll'\n");
                }
                else
                {
                    var numericDirectories = Directory.GetDirectories(VCEnv.VCToolPath64.ToString()).Where(d => Path.GetFileName(d).All(char.IsDigit));
                    var cluiDirectories    = numericDirectories.Where(d => Directory.GetFiles(d, "clui.dll").Any());
                    if (cluiDirectories.Any())
                    {
                        AddText(string.Format("\t\t'$Root$/{0}/clui.dll'\n", Path.GetFileName(cluiDirectories.First())));
                    }
                }
                AddText("\t\t'$Root$/mspdbsrv.exe'\n");
                AddText("\t\t'$Root$/mspdbcore.dll'\n");

                AddText(string.Format("\t\t'$Root$/mspft{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msobj{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/mspdb{0}.dll'\n", platformVersionNumber));

                if (VCEnv.Compiler == WindowsCompiler.VisualStudio2015)
                {
                    AddText(string.Format("\t\t'{0}/redist/x64/Microsoft.VC{1}.CRT/msvcp{2}.dll'\n", VCEnv.VCInstallDir, platformVersionNumber, platformVersionNumber));
                    AddText(string.Format("\t\t'{0}/redist/x64/Microsoft.VC{1}.CRT/vccorlib{2}.dll'\n", VCEnv.VCInstallDir, platformVersionNumber, platformVersionNumber));
                }
                else
                {
                    //VS 2017 is really confusing in terms of version numbers and paths so these values might need to be modified depending on what version of the tool chain you
                    // chose to install.
                    AddText(string.Format("\t\t'{0}/Redist/MSVC/14.12.25810/x64/Microsoft.VC141.CRT/msvcp{1}.dll'\n", VCEnv.VCInstallDir, platformVersionNumber));
                    AddText(string.Format("\t\t'{0}/Redist/MSVC/14.12.25810/x64/Microsoft.VC141.CRT/vccorlib{1}.dll'\n", VCEnv.VCInstallDir, platformVersionNumber));
                }

                AddText("\t}\n"); //End extra files

                AddText("}\n\n"); //End compiler
            }

            if (envVars.ContainsKey("SCE_ORBIS_SDK_DIR"))
            {
                AddText(string.Format(".SCE_ORBIS_SDK_DIR = '{0}'\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText(string.Format(".PS4BasePath = '{0}/host_tools/bin'\n\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText("Compiler('UE4PS4Compiler') \n{\n");
                AddText("\t.Executable = '$PS4BasePath$/orbis-clang.exe'\n");
                AddText("}\n\n");
            }

            AddText("Settings \n{\n");

            // Optional cachePath user setting
            if (bEnableCaching && CachePath != "")
            {
                AddText(string.Format("\t.CachePath = '{0}'\n", CachePath));
            }

            //Start Environment
            AddText("\t.Environment = \n\t{\n");
            if (VCEnv != null)
            {
                AddText(string.Format("\t\t\"PATH={0}\\Common7\\IDE\\;{1}\",\n", VCEnv.VCInstallDir, VCEnv.VCToolPath64));
            }
            if (envVars.ContainsKey("TMP"))
            {
                AddText(string.Format("\t\t\"TMP={0}\",\n", envVars["TMP"]));
            }
            if (envVars.ContainsKey("SystemRoot"))
            {
                AddText(string.Format("\t\t\"SystemRoot={0}\",\n", envVars["SystemRoot"]));
            }
            if (envVars.ContainsKey("INCLUDE"))
            {
                AddText(string.Format("\t\t\"INCLUDE={0}\",\n", envVars["INCLUDE"]));
            }
            if (envVars.ContainsKey("LIB"))
            {
                AddText(string.Format("\t\t\"LIB={0}\",\n", envVars["LIB"]));
            }

            AddText("\t}\n");             //End environment
            AddText("}\n\n");             //End Settings
        }
Пример #17
0
        public override CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List <FileItem> RCFiles)
        {
            var EnvVars = VCEnvironment.SetEnvironment(Environment.Config.Target.Platform, false);

            CPPOutput Result = new CPPOutput();

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

            foreach (FileItem RCFile in RCFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.CommandDescription = "Resource";
                CompileAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory.FullName;
                CompileAction.CommandPath        = EnvVars.ResourceCompilerPath;
                CompileAction.StatusDescription  = Path.GetFileName(RCFile.AbsolutePath);

                // Suppress header spew
                CompileAction.CommandArguments += " /nologo";

                // If we're compiling for 64-bit Windows, also add the _WIN64 definition to the resource
                // compiler so that we can switch on that in the .rc file using #ifdef.
                CompileAction.CommandArguments += " /D_WIN64";

                // Language
                CompileAction.CommandArguments += " /l 0x409";

                // Include paths.
                foreach (string IncludePath in Environment.Config.CPPIncludeInfo.IncludePaths)
                {
                    CompileAction.CommandArguments += string.Format(" /i \"{0}\"", IncludePath);
                }

                // System include paths.
                foreach (var SystemIncludePath in Environment.Config.CPPIncludeInfo.SystemIncludePaths)
                {
                    CompileAction.CommandArguments += string.Format(" /i \"{0}\"", SystemIncludePath);
                }

                // Preprocessor definitions.
                foreach (string Definition in Environment.Config.Definitions)
                {
                    CompileAction.CommandArguments += string.Format(" /d \"{0}\"", Definition);
                }

                // Add the RES file to the produced item list.
                FileItem CompiledResourceFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        Environment.Config.OutputDirectory,
                        Path.GetFileName(RCFile.AbsolutePath) + ".res"
                        )
                    );
                CompileAction.ProducedItems.Add(CompiledResourceFile);
                CompileAction.CommandArguments += string.Format(" /fo \"{0}\"", CompiledResourceFile.AbsolutePath);
                Result.ObjectFiles.Add(CompiledResourceFile);

                // Add the RC file as a prerequisite of the action.
                CompileAction.CommandArguments += string.Format(" \"{0}\"", RCFile.AbsolutePath);

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

            return(Result);
        }
Пример #18
0
        private void WriteEnvironmentSetup()
        {
            DirectoryReference VCInstallDir = null;
            string             VCToolPath64 = "";
            VCEnvironment      VCEnv        = null;

            try
            {
                VCEnv = VCEnvironment.Create(WindowsPlatform.GetDefaultCompiler(null), UnrealTargetPlatform.Win64, WindowsArchitecture.x64, null, null, null);
            }
            catch (Exception)
            {
                Log.TraceError("Failed to get Visual Studio environment.");
            }

            // Copy environment into a case-insensitive dictionary for easier key lookups
            Dictionary <string, string> envVars = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
            {
                envVars[(string)entry.Key] = (string)entry.Value;
            }

            if (envVars.ContainsKey("CommonProgramFiles"))
            {
                AddText("#import CommonProgramFiles\n");
            }

            if (envVars.ContainsKey("DXSDK_DIR"))
            {
                AddText("#import DXSDK_DIR\n");
            }

            if (envVars.ContainsKey("DurangoXDK"))
            {
                AddText("#import DurangoXDK\n");
            }

            if (VCEnv != null)
            {
                string platformVersionNumber = "VSVersionUnknown";

                switch (VCEnv.Compiler)
                {
                case WindowsCompiler.VisualStudio2017:
                    // For now we are working with the 140 version, might need to change to 141 or 150 depending on the version of the Toolchain you chose
                    // to install
                    platformVersionNumber = "140";
                    break;

                case WindowsCompiler.VisualStudio2019:
                    platformVersionNumber = "140";
                    break;

                default:
                    string exceptionString = "Error: Unsupported Visual Studio Version.";
                    Log.TraceError(exceptionString);
                    throw new BuildException(exceptionString);
                }


                if (!WindowsPlatform.TryGetVSInstallDir(WindowsPlatform.GetDefaultCompiler(null), out VCInstallDir))
                {
                    string exceptionString = "Error: Cannot locate Visual Studio Installation.";
                    Log.TraceError(exceptionString);
                    throw new BuildException(exceptionString);
                }

                VCToolPath64 = VCEnv.CompilerPath.Directory.ToString() + "\\";

                AddText(string.Format(".WindowsSDKBasePath = '{0}'\n", VCEnv.WindowsSdkDir));

                AddText("Compiler('UE4ResourceCompiler') \n{\n");
                AddText(string.Format("\t.Executable = '{0}'\n", VCEnv.ResourceCompilerPath));
                AddText("\t.CompilerFamily  = 'custom'\n");
                AddText("}\n\n");


                AddText("Compiler('UE4Compiler') \n{\n");

                AddText(string.Format("\t.Root = '{0}'\n", VCEnv.CompilerPath.Directory));
                AddText("\t.Executable = '$Root$/cl.exe'\n");
                AddText("\t.ExtraFiles =\n\t{\n");
                AddText("\t\t'$Root$/c1.dll'\n");
                AddText("\t\t'$Root$/c1xx.dll'\n");
                AddText("\t\t'$Root$/c2.dll'\n");


                if (File.Exists(FileReference.Combine(VCEnv.CompilerPath.Directory, "1033/clui.dll").ToString())) //Check English first...
                {
                    AddText("\t\t'$Root$/1033/clui.dll'\n");
                }
                else
                {
                    var numericDirectories = Directory.GetDirectories(VCToolPath64).Where(d => Path.GetFileName(d).All(char.IsDigit));
                    var cluiDirectories    = numericDirectories.Where(d => Directory.GetFiles(d, "clui.dll").Any());
                    if (cluiDirectories.Any())
                    {
                        AddText(string.Format("\t\t'$Root$/{0}/clui.dll'\n", Path.GetFileName(cluiDirectories.First())));
                    }
                }
                AddText("\t\t'$Root$/mspdbsrv.exe'\n");
                AddText("\t\t'$Root$/mspdbcore.dll'\n");



                AddText(string.Format("\t\t'$Root$/mspft{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msobj{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/mspdb{0}.dll'\n", platformVersionNumber));


                var redistDirs = Directory.GetDirectories(VCInstallDir.ToString() + "\\VC\\Redist\\MSVC\\", "*", SearchOption.TopDirectoryOnly);



                if (redistDirs.Length > 0)
                {
                    Regex  regex     = new Regex(@"\d{2}\.\d{2}\.\d{5}$");
                    string redistDir = redistDirs.First((s) =>
                    {
                        return(regex.IsMatch(s));
                    });
                    if (VCEnv.Compiler == WindowsCompiler.VisualStudio2019)
                    {
                        AddText(string.Format("\t\t'{0}/x64/Microsoft.VC142.CRT/msvcp{1}.dll'\n", redistDir, platformVersionNumber));
                        AddText(string.Format("\t\t'{0}/x64/Microsoft.VC142.CRT/vccorlib{1}.dll'\n", redistDir, platformVersionNumber));
                        AddText("\t\t'$Root$/tbbmalloc.dll'\n");
                    }
                    else if (VCEnv.Compiler == WindowsCompiler.VisualStudio2017)
                    {
                        //VS 2017 is really confusing in terms of version numbers and paths so these values might need to be modified depending on what version of the tool chain you
                        // chose to install.
                        AddText(string.Format("\t\t'{0}/x64/Microsoft.VC141.CRT/msvcp{1}.dll'\n", redistDir, platformVersionNumber));
                        AddText(string.Format("\t\t'{0}/x64/Microsoft.VC141.CRT/vccorlib{1}.dll'\n", redistDir, platformVersionNumber));
                    }
                }

                AddText("\t}\n"); //End extra files

                AddText("}\n\n"); //End compiler
            }

            if (envVars.ContainsKey("SCE_ORBIS_SDK_DIR"))
            {
                AddText(string.Format(".SCE_ORBIS_SDK_DIR = '{0}'\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText(string.Format(".PS4BasePath = '{0}/host_tools/bin'\n\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText("Compiler('UE4PS4Compiler') \n{\n");
                AddText("\t.Executable = '$PS4BasePath$/orbis-clang.exe'\n");
                AddText("\t.ExtraFiles = '$PS4BasePath$/orbis-snarl.exe'\n");
                AddText("}\n\n");
            }

            AddText("Settings \n{\n");

            // Optional cachePath user setting
            if (bEnableCaching && CachePath != "")
            {
                AddText(string.Format("\t.CachePath = '{0}'\n", CachePath));
            }

            //Start Environment
            AddText("\t.Environment = \n\t{\n");
            if (VCEnv != null)
            {
                AddText(string.Format("\t\t\"PATH={0}\\Common7\\IDE\\;{1};{2}\",\n", VCInstallDir.ToString(), VCToolPath64, VCEnv.ResourceCompilerPath.Directory));
                if (VCEnv.IncludePaths.Count() > 0)
                {
                    AddText(string.Format("\t\t\"INCLUDE={0}\",\n", String.Join(";", VCEnv.IncludePaths.Select(x => x))));
                }

                if (VCEnv.LibraryPaths.Count() > 0)
                {
                    AddText(string.Format("\t\t\"LIB={0}\",\n", String.Join(";", VCEnv.LibraryPaths.Select(x => x))));
                }
            }
            if (envVars.ContainsKey("TMP"))
            {
                AddText(string.Format("\t\t\"TMP={0}\",\n", envVars["TMP"]));
            }
            if (envVars.ContainsKey("SystemRoot"))
            {
                AddText(string.Format("\t\t\"SystemRoot={0}\",\n", envVars["SystemRoot"]));
            }
            if (envVars.ContainsKey("INCLUDE"))
            {
                AddText(string.Format("\t\t\"INCLUDE={0}\",\n", envVars["INCLUDE"]));
            }
            if (envVars.ContainsKey("LIB"))
            {
                AddText(string.Format("\t\t\"LIB={0}\",\n", envVars["LIB"]));
            }

            AddText("\t}\n"); //End environment


            AddText("}\n\n"); //End Settings
        }
Пример #19
0
        public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly)
        {
            var EnvVars = VCEnvironment.SetEnvironment(LinkEnvironment.Config.Target.Platform, false);

            if (LinkEnvironment.Config.bIsBuildingDotNetAssembly)
            {
                return(FileItem.GetItemByFileReference(LinkEnvironment.Config.OutputFilePath));
            }

            bool bIsBuildingLibrary = LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly;
            bool bIncludeDependentLibrariesInLibrary = bIsBuildingLibrary && LinkEnvironment.Config.bIncludeDependentLibrariesInLibrary;

            // Get link arguments.
            StringBuilder Arguments = new StringBuilder();

            if (bIsBuildingLibrary)
            {
                AppendLibArguments(LinkEnvironment, Arguments);
            }
            else
            {
                AppendLinkArguments(LinkEnvironment, Arguments);
            }



            // If we're only building an import library, add the '/DEF' option that tells the LIB utility
            // to simply create a .LIB file and .EXP file, and don't bother validating imports
            if (bBuildImportLibraryOnly)
            {
                Arguments.Append(" /DEF");

                // Ensure that the import library references the correct filename for the linked binary.
                Arguments.AppendFormat(" /NAME:\"{0}\"", LinkEnvironment.Config.OutputFilePath.GetFileName());
            }


            // Add delay loaded DLLs.
            if (!bIsBuildingLibrary)
            {
                // Delay-load these DLLs.
                foreach (string DelayLoadDLL in LinkEnvironment.Config.DelayLoadDLLs)
                {
                    Arguments.AppendFormat(" /DELAYLOAD:\"{0}\"", DelayLoadDLL);
                }
            }

            // @todo UE4 DLL: Why do I need LIBPATHs to build only export libraries with /DEF? (tbbmalloc.lib)
            if (!LinkEnvironment.Config.bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary))
            {
                // Add the library paths to the argument list.
                foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths)
                {
                    Arguments.AppendFormat(" /LIBPATH:\"{0}\"", LibraryPath);
                }

                // Add the excluded default libraries to the argument list.
                foreach (string ExcludedLibrary in LinkEnvironment.Config.ExcludedLibraries)
                {
                    Arguments.AppendFormat(" /NODEFAULTLIB:\"{0}\"", ExcludedLibrary);
                }
            }

            // For targets that are cross-referenced, we don't want to write a LIB file during the link step as that
            // file will clobber the import library we went out of our way to generate during an earlier step.  This
            // file is not needed for our builds, but there is no way to prevent MSVC from generating it when
            // linking targets that have exports.  We don't want this to clobber our LIB file and invalidate the
            // existing timstamp, so instead we simply emit it with a different name
            FileReference ImportLibraryFilePath = FileReference.Combine(LinkEnvironment.Config.IntermediateDirectory,
                                                                        LinkEnvironment.Config.OutputFilePath.GetFileNameWithoutExtension() + ".lib");

            if (LinkEnvironment.Config.bIsCrossReferenced && !bBuildImportLibraryOnly)
            {
                ImportLibraryFilePath += ".suppressed";
            }

            FileItem OutputFile;

            if (bBuildImportLibraryOnly)
            {
                OutputFile = FileItem.GetItemByFileReference(ImportLibraryFilePath);
            }
            else
            {
                OutputFile = FileItem.GetItemByFileReference(LinkEnvironment.Config.OutputFilePath);
                OutputFile.bNeedsHotReloadNumbersDLLCleanUp = LinkEnvironment.Config.bIsBuildingDLL;
            }

            List <FileItem> ProducedItems = new List <FileItem>();

            ProducedItems.Add(OutputFile);

            List <FileItem> PrerequisiteItems = new List <FileItem>();

            // Add the input files to a response file, and pass the response file on the command-line.
            List <string> InputFileNames = new List <string>();

            foreach (FileItem InputFile in LinkEnvironment.InputFiles)
            {
                InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath));
                PrerequisiteItems.Add(InputFile);
            }

            if (!bBuildImportLibraryOnly)
            {
                // Add input libraries as prerequisites, too!
                foreach (FileItem InputLibrary in LinkEnvironment.InputLibraries)
                {
                    InputFileNames.Add(string.Format("\"{0}\"", InputLibrary.AbsolutePath));
                    PrerequisiteItems.Add(InputLibrary);
                }
            }

            if (!bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary))
            {
                foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries)
                {
                    InputFileNames.Add(string.Format("\"{0}\"", AdditionalLibrary));

                    // If the library file name has a relative path attached (rather than relying on additional
                    // lib directories), then we'll add it to our prerequisites list.  This will allow UBT to detect
                    // when the binary needs to be relinked because a dependent external library has changed.
                    //if( !String.IsNullOrEmpty( Path.GetDirectoryName( AdditionalLibrary ) ) )
                    {
                        PrerequisiteItems.Add(FileItem.GetItemByPath(AdditionalLibrary));
                    }
                }
            }

            // Create a response file for the linker
            FileReference ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile);

            // Never create response files when we are only generating IntelliSense data
            if (!ProjectFileGenerator.bGenerateProjectFiles)
            {
                ResponseFile.Create(ResponseFileName, InputFileNames);
            }
            Arguments.AppendFormat(" @\"{0}\"", ResponseFileName);

            // Add the output file to the command-line.
            Arguments.AppendFormat(" /OUT:\"{0}\"", OutputFile.AbsolutePath);

            if (bBuildImportLibraryOnly || (LinkEnvironment.Config.bHasExports && !bIsBuildingLibrary))
            {
                // An export file is written to the output directory implicitly; add it to the produced items list.
                FileReference ExportFilePath = ImportLibraryFilePath.ChangeExtension(".exp");
                FileItem      ExportFile     = FileItem.GetItemByFileReference(ExportFilePath);
                ProducedItems.Add(ExportFile);
            }

            if (!bIsBuildingLibrary)
            {
                // Xbox 360 LTCG does not seem to produce those.
                if (LinkEnvironment.Config.bHasExports &&
                    (LinkEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Shipping))
                {
                    // Write the import library to the output directory for nFringe support.
                    FileItem ImportLibraryFile = FileItem.GetItemByFileReference(ImportLibraryFilePath);
                    Arguments.AppendFormat(" /IMPLIB:\"{0}\"", ImportLibraryFilePath);
                    ProducedItems.Add(ImportLibraryFile);
                }

                if (LinkEnvironment.Config.bCreateDebugInfo)
                {
                    // Write the PDB file to the output directory.
                    FileReference PDBFilePath = FileReference.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".pdb");
                    FileItem      PDBFile     = FileItem.GetItemByFileReference(PDBFilePath);
                    Arguments.AppendFormat(" /PDB:\"{0}\"", PDBFilePath);
                    ProducedItems.Add(PDBFile);

                    // Write the MAP file to the output directory.
#if false
                    if (true)
                    {
                        string   MAPFilePath = Path.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".map");
                        FileItem MAPFile     = FileItem.GetItemByFileReference(MAPFilePath);
                        LinkAction.CommandArguments += string.Format(" /MAP:\"{0}\"", MAPFilePath);
                        LinkAction.ProducedItems.Add(MAPFile);
                    }
#endif
                }

                // Add the additional arguments specified by the environment.
                Arguments.Append(LinkEnvironment.Config.AdditionalArguments);
            }

            // Create an action that invokes the linker.
            Action LinkAction = new Action(ActionType.Link);
            LinkAction.CommandDescription = "Link";
            LinkAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory.FullName;
            LinkAction.CommandPath        = bIsBuildingLibrary ? EnvVars.LibraryLinkerPath : EnvVars.LinkerPath;
            LinkAction.CommandArguments   = Arguments.ToString();
            LinkAction.ProducedItems.AddRange(ProducedItems);
            LinkAction.PrerequisiteItems.AddRange(PrerequisiteItems);
            LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath);

            // Tell the action that we're building an import library here and it should conditionally be
            // ignored as a prerequisite for other actions
            LinkAction.bProducesImportLibrary = bBuildImportLibraryOnly || LinkEnvironment.Config.bIsBuildingDLL;

            // Only execute linking on the local PC.
            LinkAction.bCanExecuteRemotely = false;

            Log.TraceVerbose("     Linking: " + LinkAction.StatusDescription);
            Log.TraceVerbose("     Command: " + LinkAction.CommandArguments);

            return(OutputFile);
        }
Пример #20
0
        public override void ValidateTarget(TargetRules Target)
        {
            // WindowsTargetRules are reused for HoloLens, so that build modules can keep the model that reuses "windows" configs for most cases
            // That means overriding those settings here that need to be adjusted for HoloLens

            // Compiler version and pix flags must be reloaded from the HoloLens hive

            // Currently BP-only projects don't load build-related settings from their remote ini when building UE4Game.exe
            // (see TargetRules.cs, where the possibly-null project directory is passed to ConfigCache.ReadSettings).
            // It's important for HoloLens that we *do* use the project-specific settings when building (VS 2017 vs 2015 and
            // retail Windows Store are both examples).  Possibly this should be done on all platforms?  But in the interest
            // of not changing behavior on other platforms I'm limiting the scope.

            DirectoryReference IniDirRef = DirectoryReference.FromFile(Target.ProjectFile);

            if (IniDirRef == null && !string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()))
            {
                IniDirRef = new DirectoryReference(UnrealBuildTool.GetRemoteIniPath());
            }

            // Stash the current compiler choice (accounts for command line) in case ReadSettings reverts it to default
            WindowsCompiler CompilerBeforeReadSettings = Target.HoloLensPlatform.Compiler;

            ConfigCache.ReadSettings(IniDirRef, Platform, Target.HoloLensPlatform);

            if (Target.HoloLensPlatform.Compiler == WindowsCompiler.Default)
            {
                if (CompilerBeforeReadSettings != WindowsCompiler.Default)
                {
                    // Previous setting was more specific, use that
                    Target.HoloLensPlatform.Compiler = CompilerBeforeReadSettings;
                }
                else
                {
                    Target.HoloLensPlatform.Compiler = WindowsPlatform.GetDefaultCompiler(Target.ProjectFile);
                }
            }

            if (!Target.bGenerateProjectFiles)
            {
                Log.TraceInformationOnce("Using {0} architecture for deploying to HoloLens device", Target.HoloLensPlatform.Architecture);
            }

            Target.WindowsPlatform.Compiler             = Target.HoloLensPlatform.Compiler;
            Target.WindowsPlatform.Architecture         = Target.HoloLensPlatform.Architecture;
            Target.WindowsPlatform.bPixProfilingEnabled = Target.HoloLensPlatform.bPixProfilingEnabled;
            Target.WindowsPlatform.bUseWindowsSDK10     = true;

            Target.bDeployAfterCompile = true;
            Target.bCompileNvCloth     = false;              // requires CUDA

            // Disable Simplygon support if compiling against the NULL RHI.
            if (Target.GlobalDefinitions.Contains("USE_NULL_RHI=1"))
            {
                Target.bCompileSpeedTree = false;
            }

            // Use shipping binaries to avoid dependency on nvToolsExt which fails WACK.
            if (Target.Configuration == UnrealTargetConfiguration.Shipping)
            {
                Target.bUseShippingPhysXLibraries = true;
            }

            // Be resilient to SDKs being uninstalled but still referenced in the INI file
            VersionNumber      SelectedWindowsSdkVersion;
            DirectoryReference SelectedWindowsSdkDir;

            if (!WindowsPlatform.TryGetWindowsSdkDir(Target.HoloLensPlatform.Win10SDKVersionString, out SelectedWindowsSdkVersion, out SelectedWindowsSdkDir))
            {
                Target.HoloLensPlatform.Win10SDKVersionString = "Latest";
            }

            // Initialize the VC environment for the target, and set all the version numbers to the concrete values we chose.
            VCEnvironment Environment = VCEnvironment.Create(Target.WindowsPlatform.Compiler, Platform, Target.WindowsPlatform.Architecture, Target.WindowsPlatform.CompilerVersion, Target.HoloLensPlatform.Win10SDKVersionString, null);

            Target.WindowsPlatform.Environment       = Environment;
            Target.WindowsPlatform.Compiler          = Environment.Compiler;
            Target.WindowsPlatform.CompilerVersion   = Environment.CompilerVersion.ToString();
            Target.WindowsPlatform.WindowsSdkVersion = Environment.WindowsSdkVersion.ToString();

            // Windows 10 SDK version
            // Auto-detect latest compatible by default (recommended), allow for explicit override if necessary
            // Validate that the SDK isn't too old, and that the combination of VS and SDK is supported.

            Target.HoloLensPlatform.Win10SDKVersion = new Version(Environment.WindowsSdkVersion.ToString());

            if (!Target.bGenerateProjectFiles)
            {
                Log.TraceInformationOnce("Building using Windows SDK version {0} for HoloLens", Target.HoloLensPlatform.Win10SDKVersion);

                if (Target.HoloLensPlatform.Win10SDKVersion < MinimumSDKVersionRecommended)
                {
                    Log.TraceWarning("Your Windows SDK version {0} is older than the minimum recommended version ({1}) for HoloLens.  Consider upgrading.", Target.HoloLensPlatform.Win10SDKVersion, MinimumSDKVersionRecommended);
                }
                else if (Target.HoloLensPlatform.Win10SDKVersion > MaximumSDKVersionTested)
                {
                    Log.TraceInformationOnce("Your Windows SDK version ({0}) for HoloLens is newer than the highest tested with this version of UBT ({1}).  This is probably fine, but if you encounter issues consider using an earlier SDK.", Target.HoloLensPlatform.Win10SDKVersion, MaximumSDKVersionTested);
                }
            }

            HoloLensExports.InitWindowsSdkToolPath(Target.HoloLensPlatform.Win10SDKVersion.ToString());
        }
Пример #21
0
        private void WriteEnvironmentSetup()
        {
            VCEnvironment VCEnv = null;

            try
            {
                // This may fail if the caller emptied PATH; we try to ignore the problem since
                // it probably means we are building for another platform.
                VCEnv = VCEnvironment.SetEnvironment(CppPlatform.Win64, WindowsCompiler.Default);
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to get Visual Studio environment.");
            }

            // Copy environment into a case-insensitive dictionary for easier key lookups
            Dictionary <string, string> envVars = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
            {
                envVars[(string)entry.Key] = (string)entry.Value;
            }

            if (envVars.ContainsKey("CommonProgramFiles"))
            {
                AddText(string.Format(".CommonProgramFiles = '{0}'\n", envVars["CommonProgramFiles"]));
            }

            if (VCEnv != null)
            {
                AddText(string.Format(".VSBasePath = '{0}\\'\n", VCEnv.VSInstallDir));
                AddText(string.Format(".VCBasePath = '{0}\\'\n", VCEnv.VCInstallDir));
                AddText(string.Format(".WindowsSDKBasePath = '{0}'\n", VCEnv.WindowsSDKDir));

                AddText("Compiler('UE4ResourceCompiler') \n{\n");
                AddText("\t.Executable = '$WindowsSDKBasePath$/bin/x64/rc.exe'\n}\n\n");

                AddText("Compiler('UE4Compiler') \n{\n");
                AddText("\t.Root = '$VCBasePath$/bin/amd64'\n");
                AddText("\t.Executable = '$Root$/cl.exe'\n");
                AddText("\t.ExtraFiles =\n\t{\n");
                AddText("\t\t'$Root$/c1.dll'\n");
                AddText("\t\t'$Root$/c1xx.dll'\n");
                AddText("\t\t'$Root$/c2.dll'\n");
                string CompilerRoot = VCEnv.VCInstallDir + "/bin/amd64/";
                if (File.Exists(CompilerRoot + "1033/clui.dll"))                 //Check English first...
                {
                    AddText("\t\t'$Root$/1033/clui.dll'\n");
                }
                else
                {
                    var numericDirectories = Directory.GetDirectories(CompilerRoot).Where(d => Path.GetFileName(d).All(char.IsDigit));
                    var cluiDirectories    = numericDirectories.Where(d => Directory.GetFiles(d, "clui.dll").Any());
                    if (cluiDirectories.Any())
                    {
                        AddText(string.Format("\t\t'$Root$/{0}/clui.dll'\n", Path.GetFileName(cluiDirectories.First())));
                    }
                }
                AddText("\t\t'$Root$/mspdbsrv.exe'\n");
                AddText("\t\t'$Root$/mspdbcore.dll'\n");

                string platformVersionNumber = "140";

                /* Maybe not needed to compile anymore?
                 * if(!WindowsPlatform.bUseWindowsSDK10)
                 *      AddText(string.Format("\t\t'$VCBasePath$/redist/x64/Microsoft.VC{0}.CRT/msvcr{1}.dll'\n", platformVersionNumber, platformVersionNumber));
                 * else
                 *      AddText("\t\t'$WindowsSDKBasePath$/Redist/ucrt/DLLs/x64/ucrtbase.dll'\n\n");
                 */
                AddText(string.Format("\t\t'$Root$/mspft{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msobj{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$Root$/mspdb{0}.dll'\n", platformVersionNumber));
                AddText(string.Format("\t\t'$VCBasePath$/redist/x64/Microsoft.VC{0}.CRT/msvcp{1}.dll'\n", platformVersionNumber, platformVersionNumber));
                AddText(string.Format("\t\t'$VCBasePath$/redist/x64/Microsoft.VC{0}.CRT/vccorlib{1}.dll'\n", platformVersionNumber, platformVersionNumber));
                AddText("\t}\n");                 //End extra files

                AddText("}\n\n");                 //End compiler
            }

            if (envVars.ContainsKey("DurangoXDK"))
            {
                AddText(string.Format("\n.DurangoXDK = '{0}'\n", envVars["DurangoXDK"]));
                AddText("Compiler('UE4XBOneCompiler') \n{\n");
                AddText("\t.Root = '$DurangoXDK$/xdk/VC/bin/amd64'\n");
                AddText("\t.Executable = '$Root$/cl.exe'\n");
                AddText("\t.ExtraFiles =\n\t{\n");
                AddText("\t\t'$Root$/c1.dll'\n");
                AddText("\t\t'$Root$/c1ast.dll'\n");
                AddText("\t\t'$Root$/c1xx.dll'\n");
                AddText("\t\t'$Root$/c1xxast.dll'\n");
                AddText("\t\t'$Root$/c2.dll'\n");
                AddText("\t\t'$Root$/1033/clui.dll'\n");
                AddText("\t\t'$Root$/mspdbsrv.exe'\n");
                AddText("\t\t'$Root$/mspdbcore.dll'\n");
                AddText("\t\t'$Root$/vcmeta.dll'\n");
                string XBplatformVersionNumber = "110";                 //Todo: This is a bodge. Check durango env vars?
                AddText(string.Format("\t\t'$Root$/mspft{0}.dll'\n", XBplatformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msobj{0}.dll'\n", XBplatformVersionNumber));
                AddText(string.Format("\t\t'$Root$/mspdb{0}.dll'\n", XBplatformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msvcp{0}.dll'\n", XBplatformVersionNumber));
                AddText(string.Format("\t\t'$Root$/msvcr{0}.dll'\n", XBplatformVersionNumber));
                AddText(string.Format("\t\t'$Root$/vccorlib{0}.dll'\n", XBplatformVersionNumber));
                AddText("\t\t'$DurangoXDK$/xdk/crt/platform/amd64/platform.winmd'\n");
                AddText("\t\t'$DurangoXDK$/xdk/References/CommonConfiguration/Neutral/Windows.winmd'\n");
                AddText("\t\t'$DurangoXDK$/xdk/Extensions/Xbox Services API/8.0/References/CommonConfiguration/neutral/microsoft.xbox.services.winmd'\n");
                AddText("\t\t'$DurangoXDK$/xdk/Extensions/Xbox GameChat API/8.0/References/CommonConfiguration/neutral/Microsoft.Xbox.GameChat.winmd'\n");
                AddText("\t}\n");                 //End extra files
                AddText("}\n\n");                 //End compiler
            }

            if (envVars.ContainsKey("SCE_ORBIS_SDK_DIR"))
            {
                AddText(string.Format(".SCE_ORBIS_SDK_DIR = '{0}'\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText(string.Format(".PS4BasePath = '{0}/host_tools/bin'\n\n", envVars["SCE_ORBIS_SDK_DIR"]));
                AddText("Compiler('UE4PS4Compiler') \n{\n");
                AddText("\t.Executable = '$PS4BasePath$/orbis-clang.exe'\n");
                AddText("}\n\n");
            }

            AddText("Settings \n{\n");

            // Optional cachePath user setting
            if (bEnableCaching && CachePath != "")
            {
                AddText(string.Format("\t.CachePath = '{0}'\n", CachePath));
            }

            //Start Environment
            AddText("\t.Environment = \n\t{\n");
            if (VCEnv != null)
            {
                AddText("\t\t\"PATH=$VSBasePath$\\Common7\\IDE\\;$VCBasePath$\\bin\\\",\n");
            }
            if (envVars.ContainsKey("TMP"))
            {
                AddText(string.Format("\t\t\"TMP={0}\",\n", envVars["TMP"]));
            }
            if (envVars.ContainsKey("SystemRoot"))
            {
                AddText(string.Format("\t\t\"SystemRoot={0}\",\n", envVars["SystemRoot"]));
            }
            if (envVars.ContainsKey("INCLUDE"))
            {
                AddText(string.Format("\t\t\"INCLUDE={0}\",\n", envVars["INCLUDE"]));
            }
            if (envVars.ContainsKey("LIB"))
            {
                AddText(string.Format("\t\t\"LIB={0}\",\n", envVars["LIB"]));
            }

            AddText("\t}\n");             //End environment
            AddText("}\n\n");             //End Settings
        }
Пример #22
0
        static void AppendCLArguments_Global(CPPEnvironment CompileEnvironment, VCEnvironment EnvVars, StringBuilder Arguments)
        {
            // @todo fastubt: Use should be using StringBuilder instead of concatenation in all of these toolchain files.  On Mono, string builder is dramatically faster.

            // @todo fastubt: We can use '/showIncludes' to accelerate outdatedness checking, as the compiler will discover all indirect includes itself.  But, the spew is pretty noisy!
            //		-> If no files in source file chain have changed, even if the build product is outdated, we can skip using /showIncludes (relies on cache surviving)
            // Arguments.Append( " /showIncludes" );

            if( WindowsPlatform.bCompileWithClang )
            {
                // Arguments.Append( " -###" );	// @todo clang: Print Clang command-lines (instead of outputting compile results!)

                // @todo clang: We're impersonating the Visual C++ compiler by setting MSC_VER and _MSC_FULL_VER to values that MSVC would set
                string VersionString;
                switch( WindowsPlatform.Compiler )
                {
                    case WindowsCompiler.VisualStudio2012:
                        VersionString = "1700";
                        break;

                    case WindowsCompiler.VisualStudio2013:
                        VersionString = "1800";
                        break;

                    default:
                        throw new BuildException( "Unexpected value for WindowsPlatform.Compiler: " + WindowsPlatform.Compiler.ToString() );
                }
                Arguments.Append(" -fmsc-version=" + VersionString);
                Arguments.Append(" /D_MSC_FULL_VER=" + VersionString + "00000");
            }

            // @todo clang: Clang on Windows doesn't respect "#pragma warning (error: ####)", and we're not passing "/WX", so warnings are not
            // treated as errors when compiling on Windows using Clang right now.

            if( BuildConfiguration.bEnableCodeAnalysis )
            {
                Arguments.Append(" /analyze");

                // Don't cause analyze warnings to be errors
                Arguments.Append(" /analyze:WX-");

                // Report functions that use a LOT of stack space.  You can lower this value if you
                // want more aggressive checking for functions that use a lot of stack memory.
                Arguments.Append(" /analyze:stacksize81940");

                // Don't bother generating code, only analyze code (may report fewer warnings though.)
                //Arguments.Append(" /analyze:only");
            }

            // Prevents the compiler from displaying its logo for each invocation.
            Arguments.Append(" /nologo");

            // Enable intrinsic functions.
            Arguments.Append(" /Oi");

            if( WindowsPlatform.bCompileWithClang )
            {
                // Tell the Clang compiler whether we want to generate 32-bit code or 64-bit code
                if( CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64 )
                {
                    Arguments.Append( " --target=x86_64-pc-windows-msvc" );
                }
                else
                {
                    Arguments.Append( " --target=x86-pc-windows-msvc" );
                }
            }

            if (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)
            {
                // Pack struct members on 8-byte boundaries.
                Arguments.Append(" /Zp8");
            }
            else
            {
                // Pack struct members on 4-byte boundaries.
                Arguments.Append(" /Zp4");
            }

            // Separate functions for linker.
            Arguments.Append(" /Gy");

            if( !WindowsPlatform.bCompileWithClang )	// @todo clang: These options are not supported with clang-cl yet
            {
                // Relaxes floating point precision semantics to allow more optimization.
                Arguments.Append(" /fp:fast");
            }

            // Compile into an .obj file, and skip linking.
            Arguments.Append(" /c");

            // Allow 800% of the default memory allocation limit.
            Arguments.Append(" /Zm800");

            if( !WindowsPlatform.bCompileWithClang )	// @todo clang: Not supported in clang-cl yet
            {
                // Allow large object files to avoid hitting the 2^16 section limit when running with -StressTestUnity.
                Arguments.Append(" /bigobj");
            }

            // Disable "The file contains a character that cannot be represented in the current code page" warning for non-US windows.
            Arguments.Append(" /wd4819");

            if( BuildConfiguration.bUseSharedPCHs )
            {
                // @todo SharedPCH: Disable warning about PCH defines not matching .cpp defines.  We "cheat" these defines a little
                // bit to make shared PCHs work.  But it's totally safe.  Trust us.
                Arguments.Append(" /wd4651");

                // @todo SharedPCH: Disable warning about redefining *API macros.  The PCH header is compiled with various DLLIMPORTs, but
                // when a module that uses that PCH header *IS* one of those imports, that module is compiled with EXPORTS, so the macro
                // is redefined on the command-line.  We need to clobber those defines to make shared PCHs work properly!
                Arguments.Append(" /wd4005");
            }

            // If compiling as a DLL, set the relevant defines
            if (CompileEnvironment.Config.bIsBuildingDLL)
            {
                Arguments.Append(" /D _WINDLL");
            }

            // When targeting Windows XP with Visual Studio 2012+, we need to tell the compiler to use the older Windows SDK that works
            // with Windows XP (http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx)
            if( WindowsPlatform.SupportWindowsXP )
            {
                if( WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2013 )
                {
                    Arguments.Append(" /D_USING_V120_SDK71_");
                }
                else if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2012)
                {
                    Arguments.Append(" /D_USING_V110_SDK71_");
                }
            }

            // Handle Common Language Runtime support (C++/CLI)
            if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled)
            {
                Arguments.Append(" /clr");

                // Don't use default lib path, we override it explicitly to use the 4.0 reference assemblies.
                Arguments.Append(" /clr:nostdlib");
            }

            //
            //	Debug
            //
            if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
            {
                // Disable compiler optimization.
                Arguments.Append(" /Od");

                // Favor code size (especially useful for embedded platforms).
                Arguments.Append(" /Os");

                // Allow inline method expansion unless E&C support is requested
                if( !BuildConfiguration.bSupportEditAndContinue )
                {
                    Arguments.Append(" /Ob2");
                }

                if ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) ||
                    (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64))
                {
                    // Runtime stack checks are not allowed when compiling for CLR
                    if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
                    {
                        Arguments.Append(" /RTCs");
                    }
                }
            }
            //
            //	Development and LTCG
            //
            else
            {
                // Maximum optimizations if desired.
                if( CompileEnvironment.Config.OptimizeCode >= ModuleRules.CodeOptimization.InNonDebugBuilds )
                {
                    Arguments.Append(" /Ox");

                    if( !WindowsPlatform.bCompileWithClang )
                    {
                        // Allow optimized code to be debugged more easily.  This makes PDBs a bit larger, but doesn't noticeably affect
                        // compile times.  The executable code is not affected at all by this switch, only the debugging information.
                        if (EnvVars.CLExeVersion >= new Version("18.0.30723"))
                        {
                            // VC2013 Update 3 has a new flag for doing this
                            Arguments.Append(" /Zo");
                        }
                        else
                        {
                            Arguments.Append(" /d2Zi+");
                        }
                    }
                }

                // Favor code speed.
                Arguments.Append(" /Ot");

                // Only omit frame pointers on the PC (which is implied by /Ox) if wanted.
                if ( BuildConfiguration.bOmitFramePointers == false
                && ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) ||
                    (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64)))
                {
                    Arguments.Append(" /Oy-");
                }

                // Allow inline method expansion
                Arguments.Append(" /Ob2");

                //
                // LTCG
                //
                if (CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Shipping)
                {
                    if( BuildConfiguration.bAllowLTCG )
                    {
                        // Enable link-time code generation.
                        Arguments.Append(" /GL");
                    }
                }
            }

            //
            //	PC
            //
            if ((CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win32) ||
                (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.Win64))
            {
                // SSE options are not allowed when using CLR compilation or the 64 bit toolchain
                // (both enable SSE2 automatically)
                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled &&
                    CompileEnvironment.Config.Target.Platform != CPPTargetPlatform.Win64)
                {
                    // Allow the compiler to generate SSE2 instructions.
                    Arguments.Append(" /arch:SSE2");
                }

                // Prompt the user before reporting internal errors to Microsoft.
                Arguments.Append(" /errorReport:prompt");

                if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLRDisabled)
                {
                    // Enable C++ exceptions when building with the editor or when building UHT.
                    if (!WindowsPlatform.bCompileWithClang &&	// @todo clang: C++ exceptions are not supported with Clang on Windows yet
                        (CompileEnvironment.Config.bEnableExceptions || UEBuildConfiguration.bBuildEditor || UEBuildConfiguration.bForceEnableExceptions))
                    {
                        // Enable C++ exception handling, but not C exceptions.
                        Arguments.Append(" /EHsc");
                    }
                    else
                    {
                        // This is required to disable exception handling in VC platform headers.
                        CompileEnvironment.Config.Definitions.Add("_HAS_EXCEPTIONS=0");
                    }
                }
                else
                {
                    // For C++/CLI all exceptions must be left enabled
                    Arguments.Append(" /EHa");
                }
            }

            // @todo - find a better place for this.
            if (CompileEnvironment.Config.Target.Platform == CPPTargetPlatform.HTML5)
            {
                Arguments.Append(" /EHsc");
            }
            // If enabled, create debug information.
            if (CompileEnvironment.Config.bCreateDebugInfo)
            {
                // Store debug info in .pdb files.
                // @todo clang: PDB files are emited from Clang but do not fully work with Visual Studio yet (breakpoints won't hit due to "symbol read error")
                if( BuildConfiguration.bUsePDBFiles )
                {
                    // Create debug info suitable for E&C if wanted.
                    if( BuildConfiguration.bSupportEditAndContinue &&
                        // We only need to do this in debug as that's the only configuration that supports E&C.
                        CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug)
                    {
                        Arguments.Append(" /ZI");
                    }
                    // Regular PDB debug information.
                    else
                    {
                        Arguments.Append(" /Zi");
                    }
                    // We need to add this so VS won't lock the PDB file and prevent synchronous updates. This forces serialization through MSPDBSRV.exe.
                    // See http://msdn.microsoft.com/en-us/library/dn502518.aspx for deeper discussion of /FS switch.
                    if (BuildConfiguration.bUseIncrementalLinking && WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2013)
                    {
                        Arguments.Append(" /FS");
                    }
                }
                // Store C7-format debug info in the .obj files, which is faster.
                else
                {
                    Arguments.Append(" /Z7");
                }
            }

            // Specify the appropriate runtime library based on the platform and config.
            if( CompileEnvironment.Config.bUseStaticCRT )
            {
                if( CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT )
                {
                    Arguments.Append(" /MTd");
                }
                else
                {
                    Arguments.Append(" /MT");
                }
            }
            else
            {
                if( CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug && BuildConfiguration.bDebugBuildsActuallyUseDebugCRT )
                {
                    Arguments.Append(" /MDd");
                }
                else
                {
                    Arguments.Append(" /MD");
                }
            }
        }