/// <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); }
/** * 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); }
/// <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; }
/// <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); }
/** * 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; } } }
/// <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); }
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); }
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); } }
/// <summary> /// Gets the path to MSBuild.exe /// </summary> /// <returns>Path to MSBuild.exe</returns> public static string GetMSBuildToolPath() { return(VCEnvironment.GetMSBuildToolPath()); }
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 } }
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); } }
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); }
/// <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); }
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 }
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 }
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); }
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 }
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); }
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()); }
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 }
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"); } } }