Exemple #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 public PrecompiledHeaderInstance(FileItem HeaderFile, bool bOptimizeCode, bool bUseRTTI, CPPOutput Output)
 {
     this.HeaderFile    = HeaderFile;
     this.bOptimizeCode = bOptimizeCode;
     this.bUseRTTI      = bUseRTTI;
     this.Output        = Output;
 }
Exemple #2
0
        public override CPPOutput CompileRCFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> RCFiles, ActionGraph ActionGraph)
        {
            CPPOutput Result = new CPPOutput();

            if (CompileEnvironment.Architecture == "-win32")             // simulator
            {
                return(base.CompileRCFiles(CompileEnvironment, RCFiles, ActionGraph));
            }

            return(Result);
        }
Exemple #3
0
        public override CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List <FileItem> RCFiles)
        {
            CPPOutput Result = new CPPOutput();

            if (Environment.Config.Target.Architecture == "-win32")
            {
                return(base.CompileRCFiles(Target, Environment, RCFiles));
            }

            return(Result);
        }
        public override CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, List <Action> Actions)
        {
            // Create a compile action for each source file.
            CPPOutput Result = new CPPOutput();

            foreach (FileItem SourceFile in InputFiles)
            {
                FileItem ObjectFile = FileItem.GetItemByFileReference(FileReference.Combine(OutputDir, Path.GetFileName(SourceFile.AbsolutePath) + ".xo"));

                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.CommandDescription = "FakeCompile";
                CompileAction.CommandPath        = BuildHostPlatform.Current.Shell;
                // we use type/cat instead of copy so that timestamp gets updated
                if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64)
                {
                    CompileAction.CommandArguments = String.Format("/C \"type \"{0}\" > \"{1}\"\"", SourceFile, ObjectFile);
                }
                else
                {
                    CompileAction.CommandArguments = String.Format("cat {0} > {1}", Utils.EscapeShellArgument(SourceFile.AbsolutePath), Utils.EscapeShellArgument(ObjectFile.AbsolutePath));
                }
                CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory;
                CompileAction.PrerequisiteItems.Add(SourceFile);
                CompileAction.ProducedItems.Add(ObjectFile);
                CompileAction.StatusDescription   = ObjectFile.Location.GetFileName();
                CompileAction.bCanExecuteRemotely = false;
                Result.ObjectFiles.Add(ObjectFile);

                foreach (FileItem ForceIncludeFile in CompileEnvironment.ForceIncludeFiles)
                {
                    CompileAction.PrerequisiteItems.Add(ForceIncludeFile);
                }


                Actions.Add(CompileAction);
            }

            return(Result);
        }
		public virtual CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
		{
			CPPOutput Result = new CPPOutput();
			return Result;
		}
Exemple #6
0
 /// <summary>
 /// Constructor
 /// </summary>
 public PrecompiledHeaderInstance(FileItem HeaderFile, CppCompileEnvironment CompileEnvironment, CPPOutput Output)
 {
     this.HeaderFile         = HeaderFile;
     this.CompileEnvironment = CompileEnvironment;
     this.Output             = Output;
 }
        public override CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, ActionGraph ActionGraph)
        {
            // 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");
            if (EnvVars.Compiler >= WindowsCompiler.VisualStudio2015)
            {
                SharedArguments.Add("/D _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1");
            }
            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 (DirectoryReference IncludePath in EnvVars.IncludePaths)
            {
                SharedArguments.Add(String.Format("/I \"{0}\"", IncludePath));
            }
            foreach (string Definition in CompileEnvironment.Definitions)
            {
                SharedArguments.Add(String.Format("/D \"{0}\"", Definition));
            }
            foreach (FileItem ForceIncludeFile in CompileEnvironment.ForceIncludeFiles)
            {
                SharedArguments.Add(String.Format("/FI\"{0}\"", ForceIncludeFile.Location));
            }

            CPPOutput Result = new CPPOutput();

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

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

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

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

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

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

                // Write the PVS studio config file
                StringBuilder ConfigFileContents = new StringBuilder();
                foreach (DirectoryReference IncludePath in EnvVars.IncludePaths)
                {
                    ConfigFileContents.AppendFormat("exclude-path={0}\n", IncludePath.FullName);
                }
                foreach (string PathMask in ApplicationSettings.PathMasks)
                {
                    if (PathMask.Contains(":") || PathMask.Contains("\\") || PathMask.Contains("/"))
                    {
                        if (Path.IsPathRooted(PathMask) && !PathMask.Contains(":"))
                        {
                            ConfigFileContents.AppendFormat("exclude-path=*{0}*\n", PathMask);
                        }
                        else
                        {
                            ConfigFileContents.AppendFormat("exclude-path={0}\n", PathMask);
                        }
                    }
                }
                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);
                if (LicenseFile != null)
                {
                    AnalyzeAction.CommandArguments += String.Format(" --lic-file \"{0}\"", LicenseFile);
                    AnalyzeAction.PrerequisiteItems.Add(FileItem.GetItemByFileReference(LicenseFile));
                }
                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);
        }
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCLArguments_Global(CompileEnvironment);

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" /I \"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" /I \"{0}\"", IncludePath);
            }

            if ((CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled) ||
                (WinRTPlatform.ShouldCompileWinRT() == true))
            {
                // 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 += string.Format(" /AI \"{0}\"", AssemblyPath);
                }

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

                // Add private assembly references
                foreach (PrivateAssemblyInfo CurAssemblyInfo in CompileEnvironment.PrivateAssemblyDependencies)
                {
                    Arguments += string.Format(" /FU \"{0}\"", CurAssemblyInfo.FileItem.AbsolutePath);
                }
            }
            else
            {
                foreach (string AssemblyPath in CompileEnvironment.Config.SystemDotNetAssemblyPaths)
                {
                    Arguments += string.Format(" /AI \"{0}\"", AssemblyPath);
                }

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

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" /D \"{0}\"", Definition);
            }

            // Log.TraceInformation("Compile Arguments for {0}:", ModuleName);
            // Log.TraceInformation(Arguments);

            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);
                string FileArguments = "";
                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);
                    }
                }

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Generate a CPP File that just includes the precompiled header.
                    string PCHCPPFilename = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp";
                    string PCHCPPPath = Path.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 += string.Format(" /I \"{0}\"", OriginalPCHHeaderDirectory);

                    var PCHExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.WinRT].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);

                    // Add the precompiled header file to the produced items list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + PCHExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments += string.Format(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    FileArguments += string.Format(" /Fp\"{0}\"", PrecompiledHeaderFile.AbsolutePath);
                    FileArguments += string.Format(" \"{0}\"", PCHCPPFile.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 = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        FileArguments += string.Format(" /Yl{0}", FakeUniquePCHSymbolName);
                    }
                    CompileAction.StatusDescription = PCHCPPFilename;
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                        FileArguments += string.Format(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        FileArguments += string.Format(" /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 += string.Format(" /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        }
                    }

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

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

                var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.WinRT].GetBinaryExtension(UEBuildBinaryType.Object);

                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByPath(
                    Path.Combine(
                        CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                Result.ObjectFiles.Add(ObjectFile);
                FileArguments += string.Format(" /Fo\"{0}\"", ObjectFile.AbsolutePath);

                // create PDBs per-file when not using debug info, 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 (!CompileEnvironment.Config.bCreateDebugInfo || BuildConfiguration.bUsePDBFiles)
                {
                    string PDBFileName;
                    bool bActionProducesPDB = false;

                    // All files using the same PCH are required to share a PDB.
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        PDBFileName = Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    }
                    // Files creating a PCH or ungrouped C++ files use a PDB per file.
                    else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create || !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.GetItemByPath(
                            Path.Combine(
                                CompileEnvironment.Config.OutputDirectory,
                                PDBFileName + ".pdb"
                                )
                            );
                    FileArguments += string.Format(" /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)
                {
                    FileArguments += GetCLArguments_C();
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = GetVCToolPath(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration, "cl");
                CompileAction.bIsVCCompiler = true;
                CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));

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

                // @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;
        }
        public override CPPOutput CompileISPCFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
        {
            CPPOutput Result = new CPPOutput();

            if (!CompileEnvironment.bCompileISPC)
            {
                return(Result);
            }

            List <string> CompileTargets = GetISPCCompileTargets(CompileEnvironment.Platform, null);

            foreach (FileItem ISPCFile in InputFiles)
            {
                Action CompileAction = Graph.CreateAction(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";
                CompileAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory;
                CompileAction.CommandPath        = new FileReference(GetISPCHostCompilerPath(BuildHostPlatform.Current.Platform));
                CompileAction.StatusDescription  = Path.GetFileName(ISPCFile.AbsolutePath);

                // Disable remote execution to workaround mismatched case on XGE
                CompileAction.bCanExecuteRemotely = false;

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

                // Add the ISPC file to be compiled.
                Arguments.Add(String.Format(" \"{0}\"", ISPCFile.AbsolutePath));

                List <FileItem> CompiledISPCObjFiles = new List <FileItem>();
                string          TargetString         = "";

                foreach (string Target in CompileTargets)
                {
                    string ObjTarget = Target;

                    if (Target.Contains("-"))
                    {
                        // Remove lane width and gang size from obj file name
                        ObjTarget = Target.Split('-')[0];
                    }

                    FileItem CompiledISPCObjFile;

                    if (CompileTargets.Count > 1)
                    {
                        CompiledISPCObjFile = FileItem.GetItemByFileReference(
                            FileReference.Combine(
                                OutputDir,
                                Path.GetFileName(ISPCFile.AbsolutePath) + "_" + ObjTarget + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                                )
                            );
                    }
                    else
                    {
                        CompiledISPCObjFile = FileItem.GetItemByFileReference(
                            FileReference.Combine(
                                OutputDir,
                                Path.GetFileName(ISPCFile.AbsolutePath) + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                                )
                            );
                    }

                    // Add the ISA specific ISPC obj files to the produced item list.
                    CompiledISPCObjFiles.Add(CompiledISPCObjFile);

                    // Build target string. No comma on last
                    if (Target == CompileTargets[CompileTargets.Count - 1])                   // .Last()
                    {
                        TargetString += Target;
                    }
                    else
                    {
                        TargetString += Target + ",";
                    }
                }

                // Add the common ISPC obj file to the produced item list.
                FileItem CompiledISPCObjFileNoISA = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + GetISPCObjectFileSuffix(CompileEnvironment.Platform)
                        )
                    );

                CompiledISPCObjFiles.Add(CompiledISPCObjFileNoISA);

                // Add the output ISPC obj file
                Arguments.Add(String.Format("-o \"{0}\"", CompiledISPCObjFileNoISA));

                // Build target triplet
                Arguments.Add(String.Format("--target-os=\"{0}\"", GetISPCOSTarget(CompileEnvironment.Platform)));
                Arguments.Add(String.Format("--arch=\"{0}\"", GetISPCArchTarget(CompileEnvironment.Platform, null)));
                Arguments.Add(String.Format("--target=\"{0}\"", TargetString));

                if (CompileEnvironment.Configuration == CppConfiguration.Debug)
                {
                    Arguments.Add("-g -O0");
                }
                else
                {
                    Arguments.Add("-O2");
                }

                // PIC is needed for modular builds except on Windows
                if ((CompileEnvironment.bIsBuildingDLL ||
                     CompileEnvironment.bIsBuildingLibrary) &&
                    !UEBuildPlatform.IsPlatformInGroup(CompileEnvironment.Platform, UnrealPlatformGroup.Windows))
                {
                    Arguments.Add("--pic");
                }

                // Include paths. Don't use AddIncludePath() here, since it uses the full path and exceeds the max command line length.
                foreach (DirectoryReference IncludePath in CompileEnvironment.UserIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", IncludePath));
                }

                // System include paths.
                foreach (DirectoryReference SystemIncludePath in CompileEnvironment.SystemIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", SystemIncludePath));
                }

                // Preprocessor definitions.
                foreach (string Definition in CompileEnvironment.Definitions)
                {
                    Arguments.Add(String.Format("-D\"{0}\"", Definition));
                }

                // Consume the included header dependency list
                if (CompileEnvironment.bGenerateDependenciesFile)
                {
                    FileItem DependencyListFile = FileItem.GetItemByFileReference(FileReference.Combine(OutputDir, Path.GetFileName(ISPCFile.AbsolutePath) + ".txt"));
                    CompileAction.DependencyListFile = DependencyListFile;
                    CompileAction.PrerequisiteItems.Add(DependencyListFile);
                }

                CompileAction.ProducedItems.AddRange(CompiledISPCObjFiles);
                Result.ObjectFiles.AddRange(CompiledISPCObjFiles);

                FileReference ResponseFileName = new FileReference(CompiledISPCObjFileNoISA.AbsolutePath + ".response");
                FileItem      ResponseFileItem = Graph.CreateIntermediateTextFile(ResponseFileName, Arguments.Select(x => Utils.ExpandVariables(x)));
                CompileAction.CommandArguments = " @\"" + ResponseFileName + "\"";
                CompileAction.PrerequisiteItems.Add(ResponseFileItem);

                // Add the source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(ISPCFile);

                Log.TraceVerbose("   ISPC Compiling " + CompileAction.StatusDescription + ": \"" + CompileAction.CommandPath + "\"" + CompileAction.CommandArguments);
            }

            return(Result);
        }
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			var Arguments = new StringBuilder();
			var PCHArguments = new StringBuilder();

			Arguments.Append(GetCompileArguments_Global(CompileEnvironment));

			if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
			{
				// Add the precompiled header file's path to the include path so GCC can find it.
				// This needs to be before the other include paths to ensure GCC uses it instead of the source header file.
				var PrecompiledFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Mac].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
				PCHArguments.Append(" -include \"");
				PCHArguments.Append(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, ""));
				PCHArguments.Append("\"");
			}

			// Add include paths to the argument list.
			HashSet<string> AllIncludes = new HashSet<string>(CompileEnvironment.Config.CPPIncludeInfo.IncludePaths);
			AllIncludes.UnionWith(CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths);
			foreach (string IncludePath in AllIncludes)
			{
				Arguments.Append(" -I\"");

				if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac)
				{
					Arguments.Append(ConvertPath(Path.GetFullPath(IncludePath)));

					// sync any third party headers we may need
					if (IncludePath.Contains("ThirdParty"))
					{
						string[] FileList = Directory.GetFiles(IncludePath, "*.h", SearchOption.AllDirectories);
						foreach (string File in FileList)
						{
							FileItem ExternalDependency = FileItem.GetItemByPath(File);
							LocalToRemoteFileItem(ExternalDependency, true);
						}

						FileList = Directory.GetFiles(IncludePath, "*.cpp", SearchOption.AllDirectories);
						foreach (string File in FileList)
						{
							FileItem ExternalDependency = FileItem.GetItemByPath(File);
							LocalToRemoteFileItem(ExternalDependency, true);
						}
					}
				}
				else
				{
					Arguments.Append(IncludePath);
				}

				Arguments.Append("\"");
			}

			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				Arguments.Append(" -D\"");
				Arguments.Append(Definition);
				Arguments.Append("\"");
			}

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

			CPPOutput Result = new CPPOutput();
			// Create a compile action for each source file.
			foreach (FileItem SourceFile in SourceFiles)
			{
				Action CompileAction = new Action(ActionType.Compile);
				string FileArguments = "";
				string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					// Compile the file as a C++ PCH.
					FileArguments += GetCompileArguments_PCH();
				}
				else if (Extension == ".C")
				{
					// Compile the file as C code.
					FileArguments += GetCompileArguments_C();
				}
				else if (Extension == ".CC")
				{
					// Compile the file as C++ code.
					FileArguments += GetCompileArguments_CPP();
				}
				else if (Extension == ".MM")
				{
					// Compile the file as Objective-C++ code.
					FileArguments += GetCompileArguments_MM();
				}
				else if (Extension == ".M")
				{
					// Compile the file as Objective-C++ code.
					FileArguments += GetCompileArguments_M();
				}
				else
				{
					// Compile the file as C++ code.
					FileArguments += GetCompileArguments_CPP();

					// only use PCH for .cpp files
					FileArguments += PCHArguments.ToString();
				}

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

				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					var PrecompiledHeaderExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Mac].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
					// Add the precompiled header file to the produced item list.
					FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
						Path.Combine(
							CompileEnvironment.Config.OutputDirectory,
							Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledHeaderExtension
							)
						);

					FileItem RemotePrecompiledHeaderFile = LocalToRemoteFileItem(PrecompiledHeaderFile, false);
					CompileAction.ProducedItems.Add(RemotePrecompiledHeaderFile);
					Result.PrecompiledHeaderFile = RemotePrecompiledHeaderFile;

					// Add the parameters needed to compile the precompiled header file to the command-line.
					FileArguments += string.Format(" -o \"{0}\"", RemotePrecompiledHeaderFile.AbsolutePath, false);
				}
				else
				{
					if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
					{
						CompileAction.bIsUsingPCH = true;
						CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
					}
					var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Mac].GetBinaryExtension(UEBuildBinaryType.Object);
					// Add the object file to the produced item list.
					FileItem ObjectFile = FileItem.GetItemByPath(
						Path.Combine(
							CompileEnvironment.Config.OutputDirectory,
							Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
							)
						);

					FileItem RemoteObjectFile = LocalToRemoteFileItem(ObjectFile, false);
					CompileAction.ProducedItems.Add(RemoteObjectFile);
					Result.ObjectFiles.Add(RemoteObjectFile);
					FileArguments += string.Format(" -o \"{0}\"", RemoteObjectFile.AbsolutePath, false);
				}

				// Add the source file path to the command-line.
				FileArguments += string.Format(" \"{0}\"", ConvertPath(SourceFile.AbsolutePath), false);

				if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac)
				{
					CompileAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler);
				}

				CompileAction.WorkingDirectory = GetMacDevSrcRoot();
				CompileAction.CommandPath = ToolchainDir + MacCompiler;
				CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
				CompileAction.CommandDescription = "Compile";
				CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
				CompileAction.bIsGCCCompiler = true;
				// We're already distributing the command by execution on Mac.
				CompileAction.bCanExecuteRemotely = false;
				CompileAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler);
			}
			return Result;
		}
        public override CPPOutput CompileCPPFiles(CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            if (CompileEnvironment.Config.TargetArchitecture == "-win32")
            {
                return base.CompileCPPFiles(CompileEnvironment, SourceFiles, ModuleName);
            }

            string Arguments = GetCLArguments_Global(CompileEnvironment);
            string BaseSDKPath = Environment.GetEnvironmentVariable("EMSCRIPTEN");

            CPPOutput Result = new CPPOutput();

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.IncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }

            if ( ModuleName == "Launch" )
                Arguments += string.Format(" -I\"{0}\"", BaseSDKPath + "/system/lib/libcxxabi/include" );

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D{0}", Definition);
            }

            // Create a compile action for each source file.
            if (ModuleName == "Launch")
                SourceFiles.Add(FileItem.GetItemByPath(BaseSDKPath + "/system/lib/libcxxabi/src/cxa_demangle.cpp"));

            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                // Add the C++ source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(SourceFile);
                foreach (FileItem IncludedFile in CompileEnvironment.GetIncludeDependencies(SourceFile))
                {
                    CompileAction.PrerequisiteItems.Add(IncludedFile);
                }

                // Add the source file path to the command-line.
                string bfastlinkstring = bEnableFastIteration ? "" : " -c ";
                string FileArguments = string.Format(bfastlinkstring + " \"{0}\"", SourceFile.AbsolutePath);

                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByPath(
                    Path.Combine(
                        CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + (bEnableFastIteration ? ".js" : ".o")
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath);

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    FileArguments += GetCLArguments_C(CompileEnvironment.Config.TargetArchitecture);
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = PythonPath;

                string fastlinkString = SourceFile.Info.FullName.Contains("Launch") ?  " -s MAIN_MODULE=1 " : "-s SIDE_MODULE=1";
                CompileAction.CommandArguments = EMCCPath + Arguments + (bEnableFastIteration ? fastlinkString : "" )+ FileArguments + CompileEnvironment.Config.AdditionalArguments;

                System.Console.WriteLine(CompileAction.CommandArguments);
                CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
                CompileAction.StatusDetailedDescription = SourceFile.Description;
                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

                // this is the final output of the compile step (a .abc file)
                Result.ObjectFiles.Add(ObjectFile);

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

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

            return Result;
        }
        public override CPPOutput CompileRCFiles(CPPEnvironment Environment, List<FileItem> RCFiles)
        {
            CPPOutput Result = new CPPOutput();

            if (Environment.Config.TargetArchitecture == "-win32")
            {
                return base.CompileRCFiles(Environment, RCFiles);
            }

            return Result;
        }
Exemple #13
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            if (CompileEnvironment.Config.Target.Architecture == "-win32")
            {
                return(base.CompileCPPFiles(Target, CompileEnvironment, SourceFiles, ModuleName));
            }

            string Arguments = GetCLArguments_Global(CompileEnvironment);

            CPPOutput Result = new CPPOutput();

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }


            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D{0}", Definition);
            }


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

            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                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);

                // Add the source file path to the command-line.
                string FileArguments       = string.Format(" \"{0}\"", SourceFile.AbsolutePath);
                var    ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.HTML5].GetBinaryExtension(UEBuildBinaryType.Object);
                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByPath(
                    Path.Combine(
                        CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath);

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    FileArguments += GetCLArguments_C(CompileEnvironment.Config.Target.Architecture);
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath      = PythonPath;

                CompileAction.CommandArguments = EMCCPath + " " + Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;

                System.Console.WriteLine(CompileAction.CommandArguments);
                CompileAction.StatusDescription  = Path.GetFileName(SourceFile.AbsolutePath);
                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

                // this is the final output of the compile step (a .abc file)
                Result.ObjectFiles.Add(ObjectFile);

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

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

            return(Result);
        }
        public override CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
        {
            var EnvVars = VCEnvironment.SetEnvironment(Environment.Config.Target.Platform);

            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 = Path.GetFullPath(".");
                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.GetItemByPath(
                    Path.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;
        }
        public override CPPOutput CompileCPPFiles(CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCLArguments_Global(CompileEnvironment);

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.IncludePaths)
            {
                Arguments += string.Format(" /I \"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.SystemIncludePaths)
            {
                if( WindowsPlatform.bCompileWithClang )
                {
                    // @todo Clang: Clang uses a special command-line syntax for system headers.  This is used for two reasons.  The first is that Clang will automatically
                    // suppress compiler warnings in headers found in these directories, such as the DirectX SDK headers.  The other reason this is important is in the case
                    // where there the same header include path is passed as both a regular include path and a system include path (extracted from INCLUDE environment).  In
                    // this case Clang will ignore any earlier occurrence of the include path, preventing a system header include path from overriding a different system
                    // include path set later on by a module.  NOTE: When passing "-Xclang", these options will always appear at the end of the command-line string, meaning
                    // they will be forced to appear *after* all environment-variable-extracted includes.  This is technically okay though.
                    Arguments += string.Format(" -Xclang -internal-isystem -Xclang \"{0}\"", IncludePath);
                }
                else
                {
                    Arguments += string.Format(" /I \"{0}\"", IncludePath);
                }
            }

            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 += string.Format(" /AI \"{0}\"", AssemblyPath);
                }

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

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

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" /D \"{0}\"", Definition);
            }

            // Create a compile action for each source file.
            CPPOutput Result = new CPPOutput();
            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                string FileArguments = "";
                bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                // Add the C++ source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(SourceFile);
                var IncludeDependencies = CompileEnvironment.GetIncludeDependencies( SourceFile );
                foreach (FileItem IncludedFile in IncludeDependencies)
                {
                    CompileAction.PrerequisiteItems.Add(IncludedFile);
                }

                // 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 + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp";
                    string PCHCPPPath = Path.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 += string.Format(" /I \"{0}\"", OriginalPCHHeaderDirectory);

                    // Add the precompiled header file to the produced items list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".pch"
                            )
                        );
                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // @todo clang: Ideally clang-cl would support the regular MSVC arguments for PCH files, and we wouldn't need to do this manually
                    if( WindowsPlatform.bCompileWithClang )
                    {
                        // Tell Clang to generate a PCH header
                        FileArguments += " -Xclang -x -Xclang c++-header";	// @todo clang: Doesn't work do to Clang-cl overriding us at the end of the command-line (see -### option output)
                        FileArguments += string.Format(" /Fo\"{0}\"", PrecompiledHeaderFile.AbsolutePath);

                        // Clang PCH generation doesn't create an .obj file to link in, unlike MSVC
                        bEmitsObjectFile = false;
                    }
                    else
                    {
                        // Add the parameters needed to compile the precompiled header file to the command-line.
                        FileArguments += string.Format(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        FileArguments += string.Format(" /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 = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                            FileArguments += string.Format(" /Yl{0}", FakeUniquePCHSymbolName);
                        }
                    }

                    FileArguments += string.Format(" \"{0}\"", PCHCPPFile.AbsolutePath);

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

                        if( WindowsPlatform.bCompileWithClang )
                        {
                            // NOTE: With Clang, PCH headers are ALWAYS forcibly included!
                            // NOTE: This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
                            FileArguments += string.Format(" /FI\"{0}\"", Path.ChangeExtension(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath, null));
                        }
                        else
                        {
                            FileArguments += string.Format(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                            FileArguments += string.Format(" /Fp\"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath);

                            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 += string.Format( " /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                            }
                        }
                    }

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

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

                if( bEmitsObjectFile )
                {
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".obj"
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);
                    FileArguments += string.Format(" /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 + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    }
                    // Files creating a PCH use a PDB per file.
                    else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                    {
                        PDBFileName = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        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";
                    }

                    // @todo Clang: Clang doesn't emit PDB files even when debugging is enabled
                    if( !WindowsPlatform.bCompileWithClang )
                    {
                        // Specify the PDB file that the compiler should write to.
                        FileItem PDBFile = FileItem.GetItemByPath(
                                Path.Combine(
                                    CompileEnvironment.Config.OutputDirectory,
                                    PDBFileName + ".pdb"
                                    )
                                );
                        FileArguments += string.Format(" /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)
                {
                    FileArguments += GetCLArguments_C();
                }
                else
                {
                    FileArguments += GetCLArguments_CPP( CompileEnvironment );
                }

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = GetVCToolPath(CompileEnvironment.Config.TargetPlatform, CompileEnvironment.Config.TargetConfiguration, "cl");

                if( !WindowsPlatform.bCompileWithClang )
                {
                    CompileAction.bIsVCCompiler = true;
                }
                CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.StatusDetailedDescription = SourceFile.Description;

                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);
                }

                if( WindowsPlatform.bCompileWithClang )
                {
                    // Clang doesn't print the file names by default, so we'll do it ourselves
                    CompileAction.bShouldOutputStatusDescription = true;
                }
                else
                {
                    // 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;
        }
        public override CPPOutput CompileRCFiles(CPPEnvironment Environment, List<FileItem> RCFiles)
        {
            CPPOutput Result = new CPPOutput();

            foreach (FileItem RCFile in RCFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = GetVCToolPath(Environment.Config.TargetPlatform, Environment.Config.TargetConfiguration, "rc");
                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.
                if (Environment.Config.TargetPlatform == CPPTargetPlatform.Win64)
                {
                    CompileAction.CommandArguments += " /D _WIN64";
                }

                // 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)
                    {
                        CompileAction.CommandArguments += " /D_USING_V120_SDK71_";
                    }
                    else if (WindowsPlatform.Compiler == WindowsCompiler.VisualStudio2012)
                    {
                        CompileAction.CommandArguments += " /D_USING_V110_SDK71_";
                    }
                }

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

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

                // System include paths.
                foreach( var SystemIncludePath in Environment.Config.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.GetItemByPath(
                    Path.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.PrerequisiteItems.Add(RCFile);
                CompileAction.CommandArguments += string.Format(" \"{0}\"", RCFile.AbsolutePath);

                // Add the files included by the RC file as prerequisites of the action.
                foreach (FileItem IncludedFile in Environment.GetIncludeDependencies(RCFile))
                {
                    CompileAction.PrerequisiteItems.Add(IncludedFile);
                }
            }

            return Result;
        }
		public override CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
		{
			CPPOutput Result = new CPPOutput();

			if (Environment.Config.Target.Architecture == "-win32") // simulator
			{
				return base.CompileRCFiles(Target, Environment, RCFiles);
			}

			return Result;
		}
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			string Arguments = GetCLArguments_Global(CompileEnvironment);
			string PCHArguments = "";

			if (!bHasPrintedLibcxxInformation)
			{
				// inform the user which C++ library the engine is going to be compiled against - important for compatibility with third party code that uses STL
				bool bUseLibCxx = ShouldUseLibcxx(CompileEnvironment.Config.Target);
				Console.WriteLine("Using {0} standard C++ library.", bUseLibCxx ? "bundled libc++" : "compiler default (most likely libstdc++)");
				bHasPrintedLibcxxInformation = true;
			}

			if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
			{
				// Add the precompiled header file's path to the include path so Clang can find it.
				// This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
				var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Linux).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
				PCHArguments += string.Format(" -include \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, ""));
			}

			// Add include paths to the argument list.
			foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
			{
				Arguments += string.Format(" -I\"{0}\"", IncludePath);
			}
			foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
			{
				Arguments += string.Format(" -I\"{0}\"", IncludePath);
			}

			// Add preprocessor definitions to the argument list.
			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				Arguments += string.Format(" -D \"{0}\"", EscapeArgument(Definition));
			}

			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);
				string FileArguments = "";
				string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

				// Add C or C++ specific compiler arguments.
				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					FileArguments += GetCompileArguments_PCH();
				}
				else if (Extension == ".C")
				{
					// Compile the file as C code.
					FileArguments += GetCompileArguments_C();
				}
				else if (Extension == ".CC")
				{
					// Compile the file as C++ code.
					FileArguments += GetCompileArguments_CPP();
				}
				else if (Extension == ".MM")
				{
					// Compile the file as Objective-C++ code.
					FileArguments += GetCompileArguments_MM();
				}
				else if (Extension == ".M")
				{
					// Compile the file as Objective-C code.
					FileArguments += GetCompileArguments_M();
				}
				else
				{
					FileArguments += GetCompileArguments_CPP();

					// only use PCH for .cpp files
					FileArguments += PCHArguments;
				}

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

				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Linux).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
					// Add the precompiled header file to the produced item 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 += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
				}
				else
				{
					if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
					{
						CompileAction.bIsUsingPCH = true;
						CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
					}

					var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Linux).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 += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
				}

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

				CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
				if (!UsingClang())
				{
					CompileAction.CommandPath = GCCPath;
				}
				else
				{
					CompileAction.CommandPath = ClangPath;
				}
				CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
				CompileAction.CommandDescription = "Compile";
				CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
				CompileAction.bIsGCCCompiler = true;

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

				// piping output through the handler during native builds is unnecessary and reportedly causes problems with tools like octobuild.
				if (CrossCompiling())
				{
					CompileAction.OutputEventHandler = new DataReceivedEventHandler(CrossCompileOutputReceivedDataEventHandler);
				}
			}

			return Result;
		}
        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);
        }
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			if (Arches.Count == 0)
			{
				throw new BuildException("At least one architecture (armv7, x86, etc) needs to be selected in the project settings to build");
			}

			if (!bHasPrintedApiLevel)
			{
				Console.WriteLine("Compiling Native code with NDK API '{0}'", GetNdkApiLevel());
				bHasPrintedApiLevel = true;
			}

			string BaseArguments = "";

			if (CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create)
			{
				BaseArguments += " -Werror";

			}

			// Directly added NDK files for NDK extensions
			ConditionallyAddNDKSourceFiles(SourceFiles, ModuleName);

			// Deal with dynamic modules removed by architecture
			GenerateEmptyLinkFunctionsForRemovedModules(SourceFiles, ModuleName, CompileEnvironment.Config.OutputDirectory);

			// Add preprocessor definitions to the argument list.
			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				BaseArguments += string.Format(" -D \"{0}\"", Definition);
			}

			var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);
			var NDKRoot = Environment.GetEnvironmentVariable("NDKROOT").Replace("\\", "/");

			string BasePCHName = "";
			var PCHExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Android).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
			if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
			{
				BasePCHName = RemoveArchName(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath).Replace(PCHExtension, "");
			}

			// Create a compile action for each source file.
			CPPOutput Result = new CPPOutput();
			foreach (string Arch in Arches)
			{
				if (ShouldSkipModule(ModuleName, Arch))
				{
					continue;
				}

				foreach (string GPUArchitecture in GPUArchitectures)
				{
					// which toolchain to use
					string Arguments = GetCLArguments_Global(CompileEnvironment, Arch) + BaseArguments;

					switch (Arch)
					{
						case "-armv7": Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_ARM=1"; break;
						case "-arm64": Arguments += " -DPLATFORM_64BITS=1 -DPLATFORM_ANDROID_ARM64=1"; break;
						case "-x86": Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_X86=1"; break;
						case "-x64": Arguments += " -DPLATFORM_64BITS=1 -DPLATFORM_ANDROID_X64=1"; break;
						default: Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_ARM=1"; break;
					}

                    if (GPUArchitecture == "-esdeferred")
					{
						Arguments += " -DPLATFORM_ANDROIDESDEFERRED=1";
					}

					// which PCH file to include
					string PCHArguments = "";
					if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
					{
						// Add the precompiled header file's path to the include path so Clang can find it.
						// This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
						PCHArguments += string.Format(" -include \"{0}\"", InlineArchName(BasePCHName, Arch, GPUArchitecture));
					}

					// Add include paths to the argument list (filtered by architecture)
					foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
					{
						if (IsDirectoryForArch(IncludePath, Arch))
						{
							Arguments += string.Format(" -I\"{0}\"", IncludePath);
						}
					}
					foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
					{
						if (IsDirectoryForArch(IncludePath, Arch))
						{
							Arguments += string.Format(" -I\"{0}\"", IncludePath);
						}
					}

					foreach (FileItem SourceFile in SourceFiles)
					{
						Action CompileAction = new Action(ActionType.Compile);
						string FileArguments = "";
						bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";
						bool bDisableShadowWarning = false;

						// should we disable optimizations on this file?
						// @todo android - We wouldn't need this if we could disable optimizations per function (via pragma)
						bool bDisableOptimizations = false;// SourceFile.AbsolutePath.ToUpperInvariant().IndexOf("\\SLATE\\") != -1;
						if (bDisableOptimizations && CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Debug)
						{
							Log.TraceWarning("Disabling optimizations on {0}", SourceFile.AbsolutePath);
						}

						bDisableOptimizations = bDisableOptimizations || CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug;

						// Add C or C++ specific compiler arguments.
						if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
						{
							FileArguments += GetCompileArguments_PCH(bDisableOptimizations);
						}
						else if (bIsPlainCFile)
						{
							FileArguments += GetCompileArguments_C(bDisableOptimizations);

							// remove shadow variable warnings for NDK files
							if (SourceFile.AbsolutePath.Replace("\\", "/").StartsWith(NDKRoot))
							{
								bDisableShadowWarning = true;
							}
						}
						else
						{
							FileArguments += GetCompileArguments_CPP(bDisableOptimizations);

							// only use PCH for .cpp files
							FileArguments += PCHArguments;
						}

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

						if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
						{
							// Add the precompiled header file to the produced item list.
							FileItem PrecompiledHeaderFile = FileItem.GetItemByFileReference(
								FileReference.Combine(
									CompileEnvironment.Config.OutputDirectory,
									Path.GetFileName(InlineArchName(SourceFile.AbsolutePath, Arch, GPUArchitecture) + PCHExtension)
									)
								);

							CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
							Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

							// Add the parameters needed to compile the precompiled header file to the command-line.
							FileArguments += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
						}
						else
						{
							if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
							{
								CompileAction.bIsUsingPCH = true;
								FileItem ArchPrecompiledHeaderFile = FileItem.GetItemByPath(InlineArchName(BasePCHName, Arch, GPUArchitecture) + PCHExtension);
								CompileAction.PrerequisiteItems.Add(ArchPrecompiledHeaderFile);
							}

							var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.Android).GetBinaryExtension(UEBuildBinaryType.Object);

							// Add the object file to the produced item list.
							FileItem ObjectFile = FileItem.GetItemByFileReference(
								FileReference.Combine(
									CompileEnvironment.Config.OutputDirectory,
									InlineArchName(Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension, Arch, GPUArchitecture)
									)
								);
							CompileAction.ProducedItems.Add(ObjectFile);
							Result.ObjectFiles.Add(ObjectFile);

							FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
						}

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

						// Build a full argument list
						string AllArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
						AllArguments = ActionThread.ExpandEnvironmentVariables(AllArguments);
						AllArguments = AllArguments.Replace("\\", "/");

						// Remove shadow warning for this file if requested
						if (bDisableShadowWarning)
						{
							int WarningIndex = AllArguments.IndexOf(" -Wshadow");
							if (WarningIndex > 0)
							{
								AllArguments = AllArguments.Remove(WarningIndex, 9);
							}
						}

						// Create the response file
						FileReference ResponseFileName = CompileAction.ProducedItems[0].Reference + "_" + AllArguments.GetHashCode().ToString("X") + ".response";
						string ResponseArgument = string.Format("@\"{0}\"", ResponseFile.Create(ResponseFileName, new List<string> { AllArguments }).FullName);

						CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
						CompileAction.CommandPath = ClangPath;
						CompileAction.CommandArguments = ResponseArgument;
						CompileAction.StatusDescription = string.Format("{0} [{1}-{2}]", Path.GetFileName(SourceFile.AbsolutePath), Arch.Replace("-", ""), GPUArchitecture.Replace("-", ""));

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

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

			return Result;
		}
Exemple #21
0
        private LinkEnvironment SetupBinaryLinkEnvironment(ReadOnlyTargetRules Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CppCompileEnvironment CompileEnvironment, FileReference SingleFileToCompile, ISourceFileWorkingSet WorkingSet, DirectoryReference ExeDir, TargetMakefile Makefile)
        {
            LinkEnvironment         BinaryLinkEnvironment         = new LinkEnvironment(LinkEnvironment);
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CppCompileEnvironment BinaryCompileEnvironment = CreateBinaryCompileEnvironment(CompileEnvironment);

            if (BinaryCompileEnvironment.bUseSharedBuildEnvironment && Target.ProjectFile != null && IntermediateDirectory.IsUnderDirectory(Target.ProjectFile.Directory))
            {
                BinaryCompileEnvironment.bUseSharedBuildEnvironment = false;
            }

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SingleFileToCompile, WorkingSet, Makefile);

                    // Save the module outputs. In monolithic builds, this is just the object files.
                    if (Target.LinkType == TargetLinkType.Monolithic)
                    {
                        Makefile.ModuleNameToOutputItems[Module.Name] = LinkInputFiles.ToArray();
                    }

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }

                    // Force a reference to initialize module for this binary
                    if (Module.Rules.bRequiresImplementModule.Value)
                    {
                        BinaryLinkEnvironment.IncludeFunctions.Add(String.Format("IMPLEMENT_MODULE_{0}", Module.Name));
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                // Allow the module to modify the link environment for the binary.
                Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules, ExeDir);
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Set the link output file.
            BinaryLinkEnvironment.OutputFilePaths = OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.bHasExports = bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.IntermediateDirectory = IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.OutputDirectory = OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.bIsBuildingDLL     = IsBuildingDll(Type);
            BinaryLinkEnvironment.bIsBuildingLibrary = IsBuildingLibrary(Type);

            // If we don't have any resource file, use the default or compile a custom one for this module
            if (BinaryLinkEnvironment.Platform == UnrealTargetPlatform.Win32 || BinaryLinkEnvironment.Platform == UnrealTargetPlatform.Win64)
            {
                // Figure out if this binary has any custom resource files. Hacky check to ignore the resource file in the Launch module, since it contains dialogs that the engine needs and always needs to be included.
                FileItem[] CustomResourceFiles = BinaryLinkEnvironment.InputFiles.Where(x => x.Location.HasExtension(".res") && !x.Location.FullName.EndsWith("\\Launch\\PCLaunch.rc.res", StringComparison.OrdinalIgnoreCase)).ToArray();
                if (CustomResourceFiles.Length == 0)
                {
                    if (BinaryLinkEnvironment.DefaultResourceFiles.Count > 0)
                    {
                        // Use the default resource file if possible
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                    else
                    {
                        // Get the intermediate directory
                        DirectoryReference ResourceIntermediateDirectory = BinaryLinkEnvironment.IntermediateDirectory;

                        // Create a compile environment for resource files
                        CppCompileEnvironment ResourceCompileEnvironment = new CppCompileEnvironment(BinaryCompileEnvironment);

                        // @todo: This should be in some Windows code somewhere...
                        // Set the original file name macro; used in Default.rc2 to set the binary metadata fields.
                        ResourceCompileEnvironment.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OutputFilePaths[0].GetFileName() + "\"");

                        // Set the other version fields
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILT_FROM_CHANGELIST={0}", Target.Version.Changelist));
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILD_VERSION={0}", Target.BuildVersion));

                        // Otherwise compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Windows", "Resources", "Default.rc2"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(ResourceCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ResourceIntermediateDirectory, Makefile.Actions);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                }
            }

            // Add all the common resource files
            BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);

            return(BinaryLinkEnvironment);
        }
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			string Arguments = GetCompileArguments_Global(CompileEnvironment);
			string PCHArguments = "";

			if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
			{
				// Add the precompiled header file's path to the include path so GCC can find it.
				// This needs to be before the other include paths to ensure GCC uses it instead of the source header file.
				var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.IOS).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
				PCHArguments += string.Format(" -include \"{0}\"", ConvertPath(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, "")));
			}

			// Add include paths to the argument list.
			HashSet<string> AllIncludes = new HashSet<string>(CompileEnvironment.Config.CPPIncludeInfo.IncludePaths);
			AllIncludes.UnionWith(CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths);
			foreach (string IncludePath in AllIncludes)
			{
				Arguments += string.Format(" -I\"{0}\"", ConvertPath(Path.GetFullPath(IncludePath)));

				if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac)
				{
					// sync any third party headers we may need
					if (IncludePath.Contains("ThirdParty"))
					{
						string[] FileList = Directory.GetFiles(IncludePath, "*.h", SearchOption.AllDirectories);
						foreach (string File in FileList)
						{
							FileItem ExternalDependency = FileItem.GetItemByPath(File);
							LocalToRemoteFileItem(ExternalDependency, true);
						}

						FileList = Directory.GetFiles(IncludePath, "*.cpp", SearchOption.AllDirectories);
						foreach (string File in FileList)
						{
							FileItem ExternalDependency = FileItem.GetItemByPath(File);
							LocalToRemoteFileItem(ExternalDependency, true);
						}
					}
				}
			}

			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				Arguments += string.Format(" -D\"{0}\"", Definition);
			}

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

			CPPOutput Result = new CPPOutput();
			// Create a compile action for each source file.
			foreach (FileItem SourceFile in SourceFiles)
			{
				Action CompileAction = new Action(ActionType.Compile);
				string FileArguments = "";
				string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					// Compile the file as a C++ PCH.
					FileArguments += GetCompileArguments_PCH();
				}
				else if (Extension == ".C")
				{
					// Compile the file as C code.
					FileArguments += GetCompileArguments_C();
				}
				else if (Extension == ".CC")
				{
					// Compile the file as C++ code.
					FileArguments += GetCompileArguments_CPP();
				}
				else if (Extension == ".MM")
				{
					// Compile the file as Objective-C++ code.
					FileArguments += GetCompileArguments_MM();
				}
				else if (Extension == ".M")
				{
					// Compile the file as Objective-C++ code.
					FileArguments += GetCompileArguments_M();
				}
				else
				{
					// Compile the file as C++ code.
					FileArguments += GetCompileArguments_CPP();

					// only use PCH for .cpp files
					FileArguments += PCHArguments;
				}

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

				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.IOS).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
					// Add the precompiled header file to the produced item list.
					FileItem PrecompiledHeaderFile = FileItem.GetItemByFileReference(
						FileReference.Combine(
							CompileEnvironment.Config.OutputDirectory,
							Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledFileExtension
							)
						);

					FileItem RemotePrecompiledHeaderFile = LocalToRemoteFileItem(PrecompiledHeaderFile, false);
					CompileAction.ProducedItems.Add(RemotePrecompiledHeaderFile);
					Result.PrecompiledHeaderFile = RemotePrecompiledHeaderFile;

					// Add the parameters needed to compile the precompiled header file to the command-line.
					FileArguments += string.Format(" -o \"{0}\"", RemotePrecompiledHeaderFile.AbsolutePath, false);
				}
				else
				{
					if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
					{
						CompileAction.bIsUsingPCH = true;
						CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
					}
					var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.IOS).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
							)
						);

					FileItem RemoteObjectFile = LocalToRemoteFileItem(ObjectFile, false);
					CompileAction.ProducedItems.Add(RemoteObjectFile);
					Result.ObjectFiles.Add(RemoteObjectFile);
					FileArguments += string.Format(" -o \"{0}\"", RemoteObjectFile.AbsolutePath, false);
				}

				// Add the source file path to the command-line.
				FileArguments += string.Format(" \"{0}\"", ConvertPath(SourceFile.AbsolutePath), false);

				string CompilerPath = ToolchainDir + IOSCompiler;
				if (!Utils.IsRunningOnMono && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac)
				{
					CompileAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler);
				}

				string AllArgs = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
				string SourceText = System.IO.File.ReadAllText(SourceFile.AbsolutePath);
				if (UEBuildConfiguration.bCompileForSize && (SourceFile.AbsolutePath.Contains("ElementBatcher.cpp") || SourceText.Contains("ElementBatcher.cpp") || SourceFile.AbsolutePath.Contains("AnimationRuntime.cpp") || SourceText.Contains("AnimationRuntime.cpp")
					|| SourceFile.AbsolutePath.Contains("AnimEncoding.cpp") || SourceText.Contains("AnimEncoding.cpp") || SourceFile.AbsolutePath.Contains("TextRenderComponent.cpp") || SourceText.Contains("TextRenderComponent.cpp")
					|| SourceFile.AbsolutePath.Contains("SWidget.cpp") || SourceText.Contains("SWidget.cpp") || SourceFile.AbsolutePath.Contains("SCanvas.cpp") || SourceText.Contains("SCanvas.cpp") || SourceFile.AbsolutePath.Contains("ShaderCore.cpp") || SourceText.Contains("ShaderCore.cpp")
                    || SourceFile.AbsolutePath.Contains("ParticleSystemRender.cpp") || SourceText.Contains("ParticleSystemRender.cpp")))
				{
					Console.WriteLine("Forcing {0} to --O3!", SourceFile.AbsolutePath);

					AllArgs = AllArgs.Replace("-Oz", "-O3");
				}

				// RPC utility parameters are in terms of the Mac side
				CompileAction.WorkingDirectory = GetMacDevSrcRoot();
				CompileAction.CommandPath = CompilerPath;
				CompileAction.CommandArguments = AllArgs; // Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
				CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));
				CompileAction.bIsGCCCompiler = true;
				// We're already distributing the command by execution on Mac.
				CompileAction.bCanExecuteRemotely = false;
				CompileAction.bShouldOutputStatusDescription = true;
				CompileAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler);
			}
			return Result;
		}
Exemple #23
0
        public virtual CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List <FileItem> RCFiles)
        {
            CPPOutput Result = new CPPOutput();

            return(Result);
        }
Exemple #24
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            string Arguments    = GetCLArguments_Global(CompileEnvironment);
            string PCHArguments = "";

            if (CompileEnvironment.Config.bIsBuildingDLL)
            {
                Arguments += " -fPIC";
            }

            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                // Add the precompiled header file's path to the include path so Clang can find it.
                // This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
                var PrecompiledFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
                PCHArguments += string.Format(" -include \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, ""));
            }

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D \"{0}\"", Definition);
            }

            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);
                string FileArguments = "";
                string Extension     = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

                // Add C or C++ specific compiler arguments.
                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    FileArguments += GetCompileArguments_PCH();
                }
                else if (Extension == ".C")
                {
                    // Compile the file as C code.
                    FileArguments += GetCompileArguments_C();
                }
                else if (Extension == ".CC")
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();
                }
                else if (Extension == ".MM")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_MM();
                }
                else if (Extension == ".M")
                {
                    // Compile the file as Objective-C code.
                    FileArguments += GetCompileArguments_M();
                }
                else
                {
                    FileArguments += GetCompileArguments_CPP();

                    // only use PCH for .cpp files
                    FileArguments += PCHArguments;
                }

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

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    var PrecompiledFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
                    // Add the precompiled header file to the produced item list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.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 += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                    }

                    var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.Object);
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);

                    FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
                }

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

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                if (!UsingClang())
                {
                    CompileAction.CommandPath = GCCPath;
                }
                else
                {
                    CompileAction.CommandPath = ClangPath;
                }
                CompileAction.CommandArguments   = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.CommandDescription = "Compile";
                CompileAction.StatusDescription  = Path.GetFileName(SourceFile.AbsolutePath);
                CompileAction.bIsGCCCompiler     = true;

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

                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);
            }

            return(Result);
        }
        public override CPPOutput GenerateISPCHeaders(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
        {
            CPPOutput Result = new CPPOutput();

            if (!CompileEnvironment.bCompileISPC)
            {
                return(Result);
            }

            List <string> CompileTargets = GetISPCCompileTargets(CompileEnvironment.Platform, null);

            foreach (FileItem ISPCFile in InputFiles)
            {
                Action CompileAction = Graph.CreateAction(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";
                CompileAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory;
                CompileAction.CommandPath        = new FileReference(GetISPCHostCompilerPath(BuildHostPlatform.Current.Platform));
                CompileAction.StatusDescription  = Path.GetFileName(ISPCFile.AbsolutePath);

                // Disable remote execution to workaround mismatched case on XGE
                CompileAction.bCanExecuteRemotely = false;

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

                // Add the ISPC obj file as a prerequisite of the action.
                CompileAction.CommandArguments = String.Format("\"{0}\" ", ISPCFile.AbsolutePath);

                // Add the ISPC h file to the produced item list.
                FileItem ISPCIncludeHeaderFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + ".generated.dummy.h"
                        )
                    );

                // Add the ISPC file to be compiled.
                Arguments.Add(String.Format("-h \"{0}\"", ISPCIncludeHeaderFile));

                // Build target string. No comma on last
                string TargetString = "";
                foreach (string Target in CompileTargets)
                {
                    if (Target == CompileTargets[CompileTargets.Count - 1])                   // .Last()
                    {
                        TargetString += Target;
                    }
                    else
                    {
                        TargetString += Target + ",";
                    }
                }

                // Build target triplet
                Arguments.Add(String.Format("--target-os={0}", GetISPCOSTarget(CompileEnvironment.Platform)));
                Arguments.Add(String.Format("--arch={0}", GetISPCArchTarget(CompileEnvironment.Platform, null)));
                Arguments.Add(String.Format("--target={0}", TargetString));

                // PIC is needed for modular builds except on Windows
                if ((CompileEnvironment.bIsBuildingDLL ||
                     CompileEnvironment.bIsBuildingLibrary) &&
                    !UEBuildPlatform.IsPlatformInGroup(CompileEnvironment.Platform, UnrealPlatformGroup.Windows))
                {
                    Arguments.Add("--pic");
                }

                // Include paths. Don't use AddIncludePath() here, since it uses the full path and exceeds the max command line length.
                // Because ISPC response files don't support white space in arguments, paths with white space need to be passed to the command line directly.
                foreach (DirectoryReference IncludePath in CompileEnvironment.UserIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", IncludePath));
                }

                // System include paths.
                foreach (DirectoryReference SystemIncludePath in CompileEnvironment.SystemIncludePaths)
                {
                    Arguments.Add(String.Format("-I\"{0}\"", SystemIncludePath));
                }

                // Generate the included header dependency list
                if (CompileEnvironment.bGenerateDependenciesFile)
                {
                    FileItem DependencyListFile = FileItem.GetItemByFileReference(FileReference.Combine(OutputDir, Path.GetFileName(ISPCFile.AbsolutePath) + ".txt"));
                    Arguments.Add(String.Format("-MMM \"{0}\"", DependencyListFile.AbsolutePath.Replace('\\', '/')));
                    CompileAction.DependencyListFile = DependencyListFile;
                    CompileAction.ProducedItems.Add(DependencyListFile);
                }

                CompileAction.ProducedItems.Add(ISPCIncludeHeaderFile);

                FileReference ResponseFileName = new FileReference(ISPCIncludeHeaderFile.AbsolutePath + ".response");
                FileItem      ResponseFileItem = Graph.CreateIntermediateTextFile(ResponseFileName, Arguments.Select(x => Utils.ExpandVariables(x)));
                CompileAction.CommandArguments += String.Format("@\"{0}\"", ResponseFileName);
                CompileAction.PrerequisiteItems.Add(ResponseFileItem);

                // Add the source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(ISPCFile);

                FileItem ISPCFinalHeaderFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(ISPCFile.AbsolutePath) + ".generated.h"
                        )
                    );

                // Fix interrupted build issue by copying header after generation completes
                FileReference SourceFile = ISPCIncludeHeaderFile.Location;
                FileReference TargetFile = ISPCFinalHeaderFile.Location;

                FileItem SourceFileItem = FileItem.GetItemByFileReference(SourceFile);
                FileItem TargetFileItem = FileItem.GetItemByFileReference(TargetFile);

                Action CopyAction = Graph.CreateAction(ActionType.BuildProject);
                CopyAction.CommandDescription = "Copy";
                CopyAction.CommandPath        = BuildHostPlatform.Current.Shell;
                if (BuildHostPlatform.Current.ShellType == ShellType.Cmd)
                {
                    CopyAction.CommandArguments = String.Format("/C \"copy /Y \"{0}\" \"{1}\" 1>nul\"", SourceFile, TargetFile);
                }
                else
                {
                    CopyAction.CommandArguments = String.Format("-c 'cp -f \"{0}\" \"{1}\"'", SourceFile.FullName, TargetFile.FullName);
                }
                CopyAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory;
                CopyAction.PrerequisiteItems.Add(SourceFileItem);
                CopyAction.ProducedItems.Add(TargetFileItem);
                CopyAction.StatusDescription              = TargetFileItem.Location.GetFileName();
                CopyAction.bCanExecuteRemotely            = false;
                CopyAction.bShouldOutputStatusDescription = false;

                Result.GeneratedHeaderFiles.Add(TargetFileItem);

                Log.TraceVerbose("   ISPC Generating Header " + CompileAction.StatusDescription + ": \"" + CompileAction.CommandPath + "\"" + CompileAction.CommandArguments);
            }

            return(Result);
        }
Exemple #26
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCLArguments_Global(CompileEnvironment);

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" /I \"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" /I \"{0}\"", IncludePath);
            }

            if ((CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled) ||
                (WinRTPlatform.ShouldCompileWinRT() == true))
            {
                // 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 += string.Format(" /AI \"{0}\"", AssemblyPath);
                }

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

                // Add private assembly references
                foreach (PrivateAssemblyInfo CurAssemblyInfo in CompileEnvironment.PrivateAssemblyDependencies)
                {
                    Arguments += string.Format(" /FU \"{0}\"", CurAssemblyInfo.FileItem.AbsolutePath);
                }
            }
            else
            {
                foreach (string AssemblyPath in CompileEnvironment.Config.SystemDotNetAssemblyPaths)
                {
                    Arguments += string.Format(" /AI \"{0}\"", AssemblyPath);
                }

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

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" /D \"{0}\"", Definition);
            }

// Log.TraceInformation("Compile Arguments for {0}:", ModuleName);
// Log.TraceInformation(Arguments);

            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);
                string FileArguments = "";
                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);
                    }
                }

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Generate a CPP File that just includes the precompiled header.
                    string   PCHCPPFilename = "PCH." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp";
                    string   PCHCPPPath     = Path.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 += string.Format(" /I \"{0}\"", OriginalPCHHeaderDirectory);

                    var PCHExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.WinRT].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);

                    // Add the precompiled header file to the produced items list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + PCHExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments += string.Format(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    FileArguments += string.Format(" /Fp\"{0}\"", PrecompiledHeaderFile.AbsolutePath);
                    FileArguments += string.Format(" \"{0}\"", PCHCPPFile.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 = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                        FileArguments += string.Format(" /Yl{0}", FakeUniquePCHSymbolName);
                    }
                    CompileAction.StatusDescription = PCHCPPFilename;
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                        FileArguments += string.Format(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        FileArguments += string.Format(" /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 += string.Format(" /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode);
                        }
                    }

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

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

                var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.WinRT].GetBinaryExtension(UEBuildBinaryType.Object);

                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByPath(
                    Path.Combine(
                        CompileEnvironment.Config.OutputDirectory,
                        Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                Result.ObjectFiles.Add(ObjectFile);
                FileArguments += string.Format(" /Fo\"{0}\"", ObjectFile.AbsolutePath);

                // create PDBs per-file when not using debug info, 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 (!CompileEnvironment.Config.bCreateDebugInfo || BuildConfiguration.bUsePDBFiles)
                {
                    string PDBFileName;
                    bool   bActionProducesPDB = false;

                    // All files using the same PCH are required to share a PDB.
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        PDBFileName = Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
                    }
                    // Files creating a PCH or ungrouped C++ files use a PDB per file.
                    else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create || !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.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            PDBFileName + ".pdb"
                            )
                        );
                    FileArguments += string.Format(" /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)
                {
                    FileArguments += GetCLArguments_C();
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory  = Path.GetFullPath(".");
                CompileAction.CommandPath       = GetVCToolPath(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration, "cl");
                CompileAction.CommandArguments  = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));

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

                // @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);
        }
        public virtual CPPOutput GenerateISPCHeaders(CppCompileEnvironment Environment, List <FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
        {
            CPPOutput Result = new CPPOutput();

            return(Result);
        }
Exemple #28
0
        private LinkEnvironment SetupBinaryLinkEnvironment(UEBuildTarget Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ActionGraph ActionGraph)
        {
            LinkEnvironment         BinaryLinkEnvironment         = LinkEnvironment.DeepCopy();
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CompileEnvironment.Config.bIsBuildingDLL     = IsBuildingDll(Config.Type);
            CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

            CPPEnvironment BinaryCompileEnvironment = CompileEnvironment.DeepCopy();

            // @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency.
            // We flag the compile environment when we build UHT so that we don't need to check
            // this for each file when generating their dependencies.
            BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool");

            // @todo: This should be in some Windows code somewhere...
            // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
            string OriginalFilename = (Config.OriginalOutputFilePaths != null) ?
                                      Config.OriginalOutputFilePaths[0].GetFileName() :
                                      Config.OutputFilePaths[0].GetFileName();

            BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SharedPCHs, ActionGraph);

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
                {
                    // Allow the module to modify the link environment for the binary.
                    Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules);
                }
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
            if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
            {
                BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
            }

            // Set the link output file.
            BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.Config.OutputDirectory = Config.OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.Config.bIsBuildingDLL     = IsBuildingDll(Config.Type);
            BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

            BinaryLinkEnvironment.Config.ProjectFile = Target.ProjectFile;

            // Add the default resources for dlls
            if (Config.Type == UEBuildBinaryType.DynamicLinkLibrary)
            {
                // Check if there's already a custom resource file
                if (!BinaryLinkEnvironment.InputFiles.Any(x => x.Reference.HasExtension(".res")))
                {
                    if (UEBuildConfiguration.bFormalBuild)
                    {
                        // For formal builds, compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        CPPEnvironment BinaryResourceCompileEnvironment = BinaryCompileEnvironment.DeepCopy();
                        BinaryResourceCompileEnvironment.Config.OutputDirectory = DirectoryReference.Combine(BinaryResourceCompileEnvironment.Config.OutputDirectory, Modules.First().Name);
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(BinaryResourceCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ActionGraph);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                    else
                    {
                        // For non-formal builds, we just want to share the default resource file between modules
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                }

                // Add all the common resource files
                BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);
            }

            return(BinaryLinkEnvironment);
        }
        private LinkEnvironment SetupBinaryLinkEnvironment(ReadOnlyTargetRules Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CppCompileEnvironment CompileEnvironment, List <PrecompiledHeaderTemplate> SharedPCHs, ISourceFileWorkingSet WorkingSet, ActionGraph ActionGraph)
        {
            LinkEnvironment         BinaryLinkEnvironment         = new LinkEnvironment(LinkEnvironment);
            HashSet <UEBuildModule> LinkEnvironmentVisitedModules = new HashSet <UEBuildModule>();
            List <UEBuildBinary>    BinaryDependencies            = new List <UEBuildBinary>();

            CppCompileEnvironment BinaryCompileEnvironment = CreateBinaryCompileEnvironment(CompileEnvironment);

            foreach (UEBuildModule Module in Modules)
            {
                List <FileItem> LinkInputFiles;
                if (Module.Binary == null || Module.Binary == this)
                {
                    // Compile each module.
                    Log.TraceVerbose("Compile module: " + Module.Name);
                    LinkInputFiles = Module.Compile(Target, ToolChain, BinaryCompileEnvironment, SharedPCHs, WorkingSet, ActionGraph);

                    // NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
                    // multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
                    // a linker warning about redundant .obj files.
                    foreach (FileItem LinkInputFile in LinkInputFiles)
                    {
                        if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
                        {
                            BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
                        }
                    }
                }
                else
                {
                    BinaryDependencies.Add(Module.Binary);
                }

                // Allow the module to modify the link environment for the binary.
                Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules);
            }


            // Allow the binary dependencies to modify the link environment.
            foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
            {
                BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
            }

            // Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
            if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
            {
                BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
            }

            // Set the link output file.
            BinaryLinkEnvironment.OutputFilePaths = OutputFilePaths.ToList();

            // Set whether the link is allowed to have exports.
            BinaryLinkEnvironment.bHasExports = bAllowExports;

            // Set the output folder for intermediate files
            BinaryLinkEnvironment.IntermediateDirectory = IntermediateDirectory;

            // Put the non-executable output files (PDB, import library, etc) in the same directory as the production
            BinaryLinkEnvironment.OutputDirectory = OutputFilePaths[0].Directory;

            // Setup link output type
            BinaryLinkEnvironment.bIsBuildingDLL     = IsBuildingDll(Type);
            BinaryLinkEnvironment.bIsBuildingLibrary = IsBuildingLibrary(Type);

            // If we don't have any resource file, use the default or compile a custom one for this module
            if (BinaryLinkEnvironment.Platform == CppPlatform.Win32 || BinaryLinkEnvironment.Platform == CppPlatform.Win64)
            {
                if (!BinaryLinkEnvironment.InputFiles.Any(x => x.Location.HasExtension(".res")))
                {
                    if (BinaryLinkEnvironment.DefaultResourceFiles.Count > 0)
                    {
                        // Use the default resource file if possible
                        BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.DefaultResourceFiles);
                    }
                    else
                    {
                        // Create a compile environment for resource files
                        CppCompileEnvironment ResourceCompileEnvironment = new CppCompileEnvironment(BinaryCompileEnvironment);

                        // @todo: This should be in some Windows code somewhere...
                        // Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
                        string OriginalFilename = (OriginalOutputFilePaths != null) ? OriginalOutputFilePaths[0].GetFileName() : OutputFilePaths[0].GetFileName();
                        ResourceCompileEnvironment.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

                        // Set the other version fields
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILT_FROM_CHANGELIST={0}", Target.Version.Changelist));
                        ResourceCompileEnvironment.Definitions.Add(String.Format("BUILD_VERSION={0}", Target.BuildVersion));

                        // Otherwise compile the default resource file per-binary, so that it gets the correct ORIGINAL_FILE_NAME macro.
                        FileItem  DefaultResourceFile   = FileItem.GetItemByFileReference(FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc"));
                        CPPOutput DefaultResourceOutput = ToolChain.CompileRCFiles(BinaryCompileEnvironment, new List <FileItem> {
                            DefaultResourceFile
                        }, ((UEBuildModuleCPP)Modules.First()).IntermediateDirectory, ActionGraph);
                        BinaryLinkEnvironment.InputFiles.AddRange(DefaultResourceOutput.ObjectFiles);
                    }
                }
            }

            // Add all the common resource files
            BinaryLinkEnvironment.InputFiles.AddRange(BinaryLinkEnvironment.CommonResourceFiles);

            return(BinaryLinkEnvironment);
        }
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName)
        {
            if (Arches.Length == 0)
            {
                throw new BuildException("At least one architecture (armv7, x86, etc) needs to be selected in the project settings to build");
            }

            if (!bHasPrintedApiLevel)
            {
                Console.WriteLine("Compiling with NDK API '{0}'", GetNdkApiLevel());
                bHasPrintedApiLevel = true;
            }

            string BaseArguments = "";

            if (CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create)
            {
                BaseArguments += " -Werror";
            }

            // Directly added NDK files for NDK extensions
            if (!UnrealBuildTool.RunningRocket())
            {
                ConditionallyAddNDKSourceFiles(SourceFiles);
            }

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                BaseArguments += string.Format(" -D \"{0}\"", Definition);
            }

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



            string BasePCHName  = "";
            var    PCHExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Android].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);

            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                BasePCHName = RemoveArchName(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath).Replace(PCHExtension, "");
            }

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

            foreach (string Arch in Arches)
            {
                foreach (string GPUArchitecture in GPUArchitectures)
                {
                    // which toolchain to use
                    string Arguments = GetCLArguments_Global(CompileEnvironment, Arch) + BaseArguments;

                    if (GPUArchitecture == "-gl4")
                    {
                        Arguments += " -DPLATFORM_ANDROIDGL4=1";
                    }
                    else if (GPUArchitecture == "-es31")
                    {
                        Arguments += " -DPLATFORM_ANDROIDES31=1";
                    }

                    // which PCH file to include
                    string PCHArguments = "";
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        // Add the precompiled header file's path to the include path so Clang can find it.
                        // This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
                        PCHArguments += string.Format(" -include \"{0}\"", InlineArchName(BasePCHName, Arch, GPUArchitecture));
                    }

                    // Add include paths to the argument list (filtered by architecture)
                    foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
                    {
                        if (IsDirectoryForArch(IncludePath, Arch))
                        {
                            Arguments += string.Format(" -I\"{0}\"", IncludePath);
                        }
                    }
                    foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
                    {
                        if (IsDirectoryForArch(IncludePath, Arch))
                        {
                            Arguments += string.Format(" -I\"{0}\"", IncludePath);
                        }
                    }

                    foreach (FileItem SourceFile in SourceFiles)
                    {
                        Action CompileAction = new Action(ActionType.Compile);
                        string FileArguments = "";
                        bool   bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                        // should we disable optimizations on this file?
                        // @todo android - We wouldn't need this if we could disable optimizations per function (via pragma)
                        bool bDisableOptimizations = false;                        // SourceFile.AbsolutePath.ToUpperInvariant().IndexOf("\\SLATE\\") != -1;
                        if (bDisableOptimizations && CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Debug)
                        {
                            Log.TraceWarning("Disabling optimizations on {0}", SourceFile.AbsolutePath);
                        }

                        bDisableOptimizations = bDisableOptimizations || CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug;

                        // Add C or C++ specific compiler arguments.
                        if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                        {
                            FileArguments += GetCompileArguments_PCH(bDisableOptimizations);
                        }
                        else if (bIsPlainCFile)
                        {
                            FileArguments += GetCompileArguments_C(bDisableOptimizations);
                        }
                        else
                        {
                            FileArguments += GetCompileArguments_CPP(bDisableOptimizations);

                            // only use PCH for .cpp files
                            FileArguments += PCHArguments;
                        }

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

                        if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                        {
                            // Add the precompiled header file to the produced item list.
                            FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                                Path.Combine(
                                    CompileEnvironment.Config.OutputDirectory,
                                    Path.GetFileName(InlineArchName(SourceFile.AbsolutePath, Arch, GPUArchitecture) + PCHExtension)
                                    )
                                );

                            CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                            Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                            // Add the parameters needed to compile the precompiled header file to the command-line.
                            FileArguments += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
                        }
                        else
                        {
                            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                            {
                                CompileAction.bIsUsingPCH = true;
                                FileItem ArchPrecompiledHeaderFile = FileItem.GetItemByPath(InlineArchName(BasePCHName, Arch, GPUArchitecture) + PCHExtension);
                                CompileAction.PrerequisiteItems.Add(ArchPrecompiledHeaderFile);
                            }

                            var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Android].GetBinaryExtension(UEBuildBinaryType.Object);

                            // Add the object file to the produced item list.
                            FileItem ObjectFile = FileItem.GetItemByPath(
                                InlineArchName(Path.Combine(
                                                   CompileEnvironment.Config.OutputDirectory,
                                                   Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension), Arch, GPUArchitecture
                                               )
                                );
                            CompileAction.ProducedItems.Add(ObjectFile);
                            Result.ObjectFiles.Add(ObjectFile);

                            FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
                        }

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

                        // Build a full argument list
                        string AllArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                        AllArguments = ActionThread.ExpandEnvironmentVariables(AllArguments);
                        AllArguments = AllArguments.Replace("\\", "/");

                        // Create the response file
                        string ResponseFileName = CompileAction.ProducedItems[0].AbsolutePath + ".response";
                        string ResponseArgument = string.Format("@\"{0}\"", ResponseFile.Create(ResponseFileName, new List <string> {
                            AllArguments
                        }));

                        CompileAction.WorkingDirectory  = Path.GetFullPath(".");
                        CompileAction.CommandPath       = ClangPath;
                        CompileAction.CommandArguments  = ResponseArgument;
                        CompileAction.StatusDescription = string.Format("{0} [{1}-{2}]", Path.GetFileName(SourceFile.AbsolutePath), Arch.Replace("-", ""), GPUArchitecture.Replace("-", ""));

                        CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

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

            return(Result);
        }
Exemple #31
0
        public virtual CPPOutput CompileRCFiles(CppCompileEnvironment Environment, List <FileItem> InputFiles, DirectoryReference OutputDir, List <Action> Actions)
        {
            CPPOutput Result = new CPPOutput();

            return(Result);
        }
        public override CPPOutput CompileCPPFiles(CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCompileArguments_Global(CompileEnvironment);
            string PCHArguments = "";

            if (CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create)
            {
                Arguments += " -Werror";
            }

            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                // Add the precompiled header file's path to the include path so GCC can find it.
                // This needs to be before the other include paths to ensure GCC uses it instead of the source header file.
                PCHArguments += string.Format(" -include \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(".gch", ""));
            }

            // Add include paths to the argument list.
            List<string> AllIncludes = CompileEnvironment.Config.IncludePaths;
            AllIncludes.AddRange(CompileEnvironment.Config.SystemIncludePaths);
            foreach (string IncludePath in AllIncludes)
            {
                Arguments += string.Format(" -I\"{0}\"", ConvertPath(Path.GetFullPath(IncludePath)));

                if (ExternalExecution.GetRuntimePlatform() != UnrealTargetPlatform.Mac)
                {
                    // sync any third party headers we may need
                    if (IncludePath.Contains("ThirdParty"))
                    {
                        string[] FileList = Directory.GetFiles(IncludePath, "*.h", SearchOption.AllDirectories);
                        foreach (string File in FileList)
                        {
                            FileItem ExternalDependency = FileItem.GetItemByPath(File);
                            LocalToRemoteFileItem(ExternalDependency, true);
                        }

                        FileList = Directory.GetFiles(IncludePath, "*.cpp", SearchOption.AllDirectories);
                        foreach (string File in FileList)
                        {
                            FileItem ExternalDependency = FileItem.GetItemByPath(File);
                            LocalToRemoteFileItem(ExternalDependency, true);
                        }
                    }
                }
            }

            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D\"{0}\"", Definition);
            }

            CPPOutput Result = new CPPOutput();
            // Create a compile action for each source file.
            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                string FileArguments = "";
                string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Compile the file as a C++ PCH.
                    FileArguments += GetCompileArguments_PCH();
                }
                else if (Extension == ".C")
                {
                    // Compile the file as C code.
                    FileArguments += GetCompileArguments_C();
                }
                else if (Extension == ".CC")
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();
                }
                else if (Extension == ".MM")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_MM();
                }
                else if (Extension == ".M")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_M();
                }
                else
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();

                    // only use PCH for .cpp files
                    FileArguments += PCHArguments;
                }

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

                if (ExternalExecution.GetRuntimePlatform() != UnrealTargetPlatform.Mac)
                {
                    QueueFileForBatchUpload(SourceFile);
                }

                foreach (FileItem IncludedFile in CompileEnvironment.GetIncludeDependencies(SourceFile))
                {
                    if (ExternalExecution.GetRuntimePlatform() != UnrealTargetPlatform.Mac)
                    {
                        QueueFileForBatchUpload(IncludedFile);
                    }

                    CompileAction.PrerequisiteItems.Add(IncludedFile);
                }

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Add the precompiled header file to the produced item list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".gch"
                            )
                        );

                    FileItem RemotePrecompiledHeaderFile = LocalToRemoteFileItem(PrecompiledHeaderFile, false);
                    CompileAction.ProducedItems.Add(RemotePrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = RemotePrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments += string.Format(" -o \"{0}\"", RemotePrecompiledHeaderFile.AbsolutePath, false);
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                    }

                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".o"
                            )
                        );

                    FileItem RemoteObjectFile = LocalToRemoteFileItem(ObjectFile, false);
                    CompileAction.ProducedItems.Add(RemoteObjectFile);
                    Result.ObjectFiles.Add(RemoteObjectFile);
                    FileArguments += string.Format(" -o \"{0}\"", RemoteObjectFile.AbsolutePath, false);
                }

                // Add the source file path to the command-line.
                FileArguments += string.Format(" \"{0}\"", ConvertPath(SourceFile.AbsolutePath), false);

                if (ExternalExecution.GetRuntimePlatform() != UnrealTargetPlatform.Mac)
                {
                    CompileAction.ActionHandler = new Action.BlockingActionHandler(RPCUtilHelper.RPCActionHandler);
                }

                CompileAction.WorkingDirectory = GetMacDevSrcRoot();
                CompileAction.CommandPath = "xcrun";
                CompileAction.CommandArguments = MacCompiler + Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));
                CompileAction.StatusDetailedDescription = SourceFile.Description;
                CompileAction.bIsGCCCompiler = true;
                // We're already distributing the command by execution on Mac.
                CompileAction.bCanExecuteRemotely = false;
                CompileAction.OutputEventHandler = new DataReceivedEventHandler(RemoteOutputReceivedEventHandler);
            }
            return Result;
        }
Exemple #33
0
        public virtual CPPOutput CompileRCFiles(CppCompileEnvironment Environment, List <FileItem> RCFiles, ActionGraph ActionGraph)
        {
            CPPOutput Result = new CPPOutput();

            return(Result);
        }
Exemple #34
0
		public override CPPOutput CompileRCFiles(UEBuildTarget Target, CPPEnvironment Environment, List<FileItem> RCFiles)
		{
			var EnvVars = VCEnvironment.SetEnvironment(Environment.Config.Target.Platform);

			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   = Path.GetFullPath(".");
				CompileAction.CommandPath        = EnvVars.ResourceCompilerPath;
				CompileAction.StatusDescription  = Path.GetFileName(RCFile.AbsolutePath);

				// Resource tool can run remotely if possible
				CompileAction.bCanExecuteRemotely = true;

				var Arguments = new StringBuilder();

				if( WindowsPlatform.bCompileWithClang )
				{ 
					CompileAction.OutputEventHandler = new DataReceivedEventHandler( ClangCompilerOutputFormatter );
				}

				// Suppress header spew
				Arguments.Append( " /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.
				if (Environment.Config.Target.Platform == CPPTargetPlatform.Win64)
				{
					AddDefinition( Arguments, "_WIN64" );
				}

				// 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_" );
				}

				// Language
				Arguments.AppendFormat( " /l 0x409" );

				// Include paths.
				foreach (string IncludePath in Environment.Config.CPPIncludeInfo.IncludePaths)
				{
					AddIncludePath( Arguments, IncludePath );
				}

				// System include paths.
				foreach( var SystemIncludePath in Environment.Config.CPPIncludeInfo.SystemIncludePaths )
				{
					AddIncludePath( Arguments, SystemIncludePath );
				}

				// Preprocessor definitions.
				foreach (string Definition in Environment.Config.Definitions)
				{
					AddDefinition( Arguments, Definition);
				}

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

				// Add the RC file as a prerequisite of the action.
				Arguments.AppendFormat(" \"{0}\"", RCFile.AbsolutePath);

				CompileAction.CommandArguments = Arguments.ToString();

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

			return Result;
		}
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			if (CompileEnvironment.Config.Target.Architecture == "-win32") // simulator
			{
				return base.CompileCPPFiles(Target, CompileEnvironment, SourceFiles, ModuleName);
			}

			string Arguments = GetCLArguments_Global(CompileEnvironment);

			CPPOutput Result = new CPPOutput();

			// Add include paths to the argument list.
			foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
			{
				Arguments += string.Format(" -I\"{0}\"", IncludePath);
			}
			foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
			{
				Arguments += string.Format(" -I\"{0}\"", IncludePath);
			}


			// Add preprocessor definitions to the argument list.
			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				Arguments += string.Format(" -D{0}", Definition);
			}

			if (bEnableTracing)
			{
				Arguments += string.Format(" -D__EMSCRIPTEN_TRACING__");
			}

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

			foreach (FileItem SourceFile in SourceFiles)
			{
				Action CompileAction = new Action(ActionType.Compile);
				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);

				// Add the source file path to the command-line.
				string FileArguments = string.Format(" \"{0}\"", SourceFile.AbsolutePath);
				var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.HTML5).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);
				FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath);

				// Add C or C++ specific compiler arguments.
				if (bIsPlainCFile)
				{
					FileArguments += GetCLArguments_C(CompileEnvironment.Config.Target.Architecture);
				}
				else
				{
					FileArguments += GetCLArguments_CPP(CompileEnvironment);
				}

				CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
				CompileAction.CommandPath = HTML5SDKInfo.Python();

				CompileAction.CommandArguments = HTML5SDKInfo.EmscriptenCompiler() + " " + Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;

				//System.Console.WriteLine(CompileAction.CommandArguments);
				CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
				CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

				// this is the final output of the compile step (a .abc file)
				Result.ObjectFiles.Add(ObjectFile);

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

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

			return Result;
		}
Exemple #36
0
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			var EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.Config.Target.Platform);

			StringBuilder SharedArguments = new StringBuilder();
			AppendCLArguments_Global(CompileEnvironment, EnvVars, SharedArguments);

			// Add include paths to the argument list.
			if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
			{
				foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
				{
					AddIncludePath( SharedArguments, IncludePath );
				}
			}
			else
			{
				foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
				{
					AddIncludePath( SharedArguments, System.IO.Path.GetFullPath(IncludePath) );
				}
			}
			foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
			{
				if( WindowsPlatform.bCompileWithClang )
				{
					// @todo Clang: Clang uses a special command-line syntax for system headers.  This is used for two reasons.  The first is that Clang will automatically 
					// suppress compiler warnings in headers found in these directories, such as the DirectX SDK headers.  The other reason this is important is in the case 
					// where there the same header include path is passed as both a regular include path and a system include path (extracted from INCLUDE environment).  In 
					// this case Clang will ignore any earlier occurrence of the include path, preventing a system header include path from overriding a different system 
					// include path set later on by a module.  NOTE: When passing "-Xclang", these options will always appear at the end of the command-line string, meaning
					// they will be forced to appear *after* all environment-variable-extracted includes.  This is technically okay though.
					if( WindowsPlatform.bUseVCCompilerArgs )
					{ 
						SharedArguments.AppendFormat(" -Xclang -internal-isystem -Xclang \"{0}\"", IncludePath);
					}
					else
					{
						SharedArguments.AppendFormat(" -isystem \"{0}\"", IncludePath);
					}
				}
				else
				{
					AddIncludePath( SharedArguments, IncludePath );
				}
			}


			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)
				{
					SharedArguments.AppendFormat(" /AI \"{0}\"", AssemblyPath);
				}

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

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

			if (!WindowsPlatform.bCompileWithClang && WindowsPlatform.bLogDetailedCompilerTimingInfo)
			{
				// Force MSVC
				SharedArguments.Append(" /Bt+");
			}

			// 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;
				AddDefinition(SharedArguments, 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";
				// ensure compiler timings are captured when we execute the action.
				if (!WindowsPlatform.bCompileWithClang && WindowsPlatform.bLogDetailedCompilerTimingInfo)
				{
					CompileAction.bPrintDebugInfo = true;
				}

				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 );
					}
				}

				if( WindowsPlatform.bCompileWithClang )
				{ 
					CompileAction.OutputEventHandler = new DataReceivedEventHandler( ClangCompilerOutputFormatter );
				}


				bool bEmitsObjectFile = true;
				if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
				{
					// Generate a CPP File that just includes the precompiled header.
					string PCHCPPFilename = "PCH." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp";
					string PCHCPPPath = Path.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 );
					AddIncludePath( FileArguments, OriginalPCHHeaderDirectory );

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

					if( WindowsPlatform.bUseVCCompilerArgs )
					{
						// 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 = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
							FileArguments.AppendFormat(" /Yl{0}", FakeUniquePCHSymbolName);
						}
					}
					else
					{
						FileArguments.Append( " -Xclang -emit-pch" );

						FileArguments.AppendFormat(" -o\"{0}\"", PrecompiledHeaderFile.AbsolutePath);

						// Clang PCH generation doesn't create an .obj file to link in, unlike MSVC
						bEmitsObjectFile = false;
					}

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

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

						if( WindowsPlatform.bCompileWithClang )
						{
							// NOTE: With Clang, PCH headers are ALWAYS forcibly included!
							// NOTE: This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
							if( WindowsPlatform.bUseVCCompilerArgs )
							{ 
								FileArguments.AppendFormat(" /FI\"{0}\"", Path.ChangeExtension(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath, null));
							}
							else
							{
								// FileArguments.Append( " -Xclang -fno-validate-pch" );	// @todo clang: Interesting option for faster performance
								FileArguments.AppendFormat(" -include-pch \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath);
							}
						}
						else
						{
							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);
							}
						}
					}

					// UnrealCodeAnalyzer requires compiled file name to be first argument.
					if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
					{
						// 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.BuildPlatformDictionary[UnrealTargetPlatform.Win64].GetBinaryExtension(UEBuildBinaryType.Object);
					// Add the object file to the produced item list.
					FileItem ObjectFile = FileItem.GetItemByPath(
						Path.Combine(
							CompileEnvironment.Config.OutputDirectory,
							Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
							)
						);
					CompileAction.ProducedItems.Add(ObjectFile);
					Result.ObjectFiles.Add(ObjectFile);
					// UnrealCodeAnalyzer requires specific position of output file.
					if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
					{
						if( WindowsPlatform.bUseVCCompilerArgs )
						{ 
							FileArguments.AppendFormat(" /Fo\"{0}\"", ObjectFile.AbsolutePath);
						}
						else
						{
							FileArguments.AppendFormat(" -o\"{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." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
					}
					// Files creating a PCH use a PDB per file.
					else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
					{
						PDBFileName = "PCH." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename);
						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.GetItemByPath(
								Path.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 = Path.GetFullPath(".");
				if (BuildConfiguration.bRunUnrealCodeAnalyzer)
				{
					CompileAction.CommandPath = System.IO.Path.Combine(CompileAction.WorkingDirectory, @"..", @"Binaries", @"Win32", @"UnrealCodeAnalyzer.exe");
				}
				else
				{
					CompileAction.CommandPath = EnvVars.CompilerPath;
				}

				string UnrealCodeAnalyzerArguments = "";
				if (BuildConfiguration.bRunUnrealCodeAnalyzer)
				{
					string UCAMode = BuildConfiguration.bUCACheckUObjectThreadSafety ? @"-CheckThreadSafety " : @"-CreateIncludeFiles ";
					var ObjectFileExtension = BuildConfiguration.bUCACheckUObjectThreadSafety ? @".tsc" : @".includes";
					FileItem ObjectFile = FileItem.GetItemByPath(Path.Combine(CompileEnvironment.Config.OutputDirectory, Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension));
					var ClangPath = System.IO.Path.Combine(CompileAction.WorkingDirectory, @"ThirdParty", @"llvm", @"3.5.0", @"bin", @"vs2013", @"x86", @"release", @"clang++.exe");
					UnrealCodeAnalyzerArguments = UCAMode + SourceFile.AbsolutePath + @" -OutputFile=""" + ObjectFile.AbsolutePath + @""" -- " + ClangPath + @" --driver-mode=cl ";
				}

				CompileAction.CommandArguments = UnrealCodeAnalyzerArguments + SharedArguments.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);
				}

				if( WindowsPlatform.bCompileWithClang || BuildConfiguration.bRunUnrealCodeAnalyzer)
				{
					// Clang doesn't print the file names by default, so we'll do it ourselves
					CompileAction.bShouldOutputStatusDescription = true;
				}
				else
				{
					// 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;
				}

				// When compiling with SN-DBS, modules that contain a #import must be built locally
				if( CompileEnvironment.Config.bBuildLocallyWithSNDBS == true && BuildConfiguration.bAllowSNDBS)
				{
					CompileAction.bCanExecuteRemotely = false;
				}
			}
			return Result;
		}
        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);
        }
        public override CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, ActionGraph ActionGraph)
        {
            string Arguments = GetCLArguments_Global(CompileEnvironment);

            CPPOutput Result = new CPPOutput();

            // Add include paths to the argument list.
            foreach (DirectoryReference IncludePath in CompileEnvironment.IncludePaths.UserIncludePaths)
            {
                AddIncludePath(ref Arguments, IncludePath);
            }
            foreach (DirectoryReference IncludePath in CompileEnvironment.IncludePaths.SystemIncludePaths)
            {
                AddIncludePath(ref Arguments, IncludePath);
            }


            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Definitions)
            {
                Arguments += string.Format(" -D{0}", Definition);
            }

            if (bEnableTracing)
            {
                Arguments += string.Format(" -D__EMSCRIPTEN_TRACING__");
            }

            // Force include all the requested headers
            foreach (FileItem ForceIncludeFile in CompileEnvironment.ForceIncludeFiles)
            {
                Arguments += String.Format(" -include \"{0}\"", ForceIncludeFile.Location);
            }

            foreach (FileItem SourceFile in InputFiles)
            {
                Action CompileAction = ActionGraph.Add(ActionType.Compile);
                CompileAction.CommandDescription = "Compile";
                CompileAction.PrerequisiteItems.AddRange(CompileEnvironment.ForceIncludeFiles);
//				CompileAction.bPrintDebugInfo = true;

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

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

                // Add the source file path to the command-line.
                string FileArguments       = string.Format(" \"{0}\"", SourceFile.AbsolutePath);
                string ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.HTML5).GetBinaryExtension(UEBuildBinaryType.Object);
                // Add the object file to the produced item list.
                FileItem ObjectFile = FileItem.GetItemByFileReference(
                    FileReference.Combine(
                        OutputDir,
                        Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                        )
                    );
                CompileAction.ProducedItems.Add(ObjectFile);
                FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath);

                // Add C or C++ specific compiler arguments.
                if (bIsPlainCFile)
                {
                    FileArguments += GetCLArguments_C(CompileEnvironment.Architecture);
                }
                else
                {
                    FileArguments += GetCLArguments_CPP(CompileEnvironment);
                }

                CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName;
                CompileAction.CommandPath      = HTML5SDKInfo.Python();

                CompileAction.CommandArguments = HTML5SDKInfo.EmscriptenCompiler() + " " + Arguments + FileArguments + CompileEnvironment.AdditionalArguments;

                //System.Console.WriteLine(CompileAction.CommandArguments);
                CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);

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

                // this is the final output of the compile step (a .abc file)
                Result.ObjectFiles.Add(ObjectFile);

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

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

            return(Result);
        }
Exemple #39
0
        public override CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, IActionGraphBuilder Graph)
        {
            // Use a subdirectory for PVS output, to avoid clobbering regular build artifacts
            OutputDir = DirectoryReference.Combine(OutputDir, "PVS");

            // Preprocess the source files with the regular toolchain
            CppCompileEnvironment PreprocessCompileEnvironment = new CppCompileEnvironment(CompileEnvironment);

            PreprocessCompileEnvironment.bPreprocessOnly = true;
            PreprocessCompileEnvironment.bEnableUndefinedIdentifierWarnings = false;             // Not sure why THIRD_PARTY_INCLUDES_START doesn't pick this up; the _Pragma appears in the preprocessed output. Perhaps in preprocess-only mode the compiler doesn't respect these?
            PreprocessCompileEnvironment.Definitions.Add("PVS_STUDIO");

            List <Action> PreprocessActions = new List <Action>();
            CPPOutput     Result            = InnerToolChain.CompileCPPFiles(PreprocessCompileEnvironment, InputFiles, OutputDir, ModuleName, new ActionGraphCapture(Graph, PreprocessActions));

            // Run the source files through PVS-Studio
            foreach (Action PreprocessAction in PreprocessActions)
            {
                if (PreprocessAction.ActionType != ActionType.Compile)
                {
                    continue;
                }

                FileItem SourceFileItem = PreprocessAction.PrerequisiteItems.FirstOrDefault(x => x.HasExtension(".c") || x.HasExtension(".cc") || x.HasExtension(".cpp"));
                if (SourceFileItem == null)
                {
                    Log.TraceWarning("Unable to find source file from command: {0} {1}", PreprocessAction.CommandArguments);
                    continue;
                }

                FileItem PreprocessedFileItem = PreprocessAction.ProducedItems.FirstOrDefault(x => x.HasExtension(".i"));
                if (PreprocessedFileItem == null)
                {
                    Log.TraceWarning("Unable to find preprocessed output file from command: {0} {1}", PreprocessAction.CommandArguments);
                    continue;
                }

                // Disable a few warnings that seem to come from the preprocessor not respecting _Pragma
                PreprocessAction.CommandArguments += " /wd4005";                 // macro redefinition
                PreprocessAction.CommandArguments += " /wd4828";                 // file contains a character starting at offset xxxx that is illegal in the current source character set

                // Write the PVS studio config file
                StringBuilder ConfigFileContents = new StringBuilder();
                foreach (DirectoryReference IncludePath in Target.WindowsPlatform.Environment.IncludePaths)
                {
                    ConfigFileContents.AppendFormat("exclude-path={0}\n", IncludePath.FullName);
                }
                if (ApplicationSettings != null && ApplicationSettings.PathMasks != null)
                {
                    foreach (string PathMask in ApplicationSettings.PathMasks)
                    {
                        if (PathMask.Contains(":") || PathMask.Contains("\\") || PathMask.Contains("/"))
                        {
                            if (Path.IsPathRooted(PathMask) && !PathMask.Contains(":"))
                            {
                                ConfigFileContents.AppendFormat("exclude-path=*{0}*\n", PathMask);
                            }
                            else
                            {
                                ConfigFileContents.AppendFormat("exclude-path={0}\n", PathMask);
                            }
                        }
                    }
                }
                if (Platform == UnrealTargetPlatform.Win64)
                {
                    ConfigFileContents.Append("platform=x64\n");
                }
                else if (Platform == UnrealTargetPlatform.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);

                string BaseFileName = PreprocessedFileItem.Location.GetFileNameWithoutExtension();

                FileReference ConfigFileLocation = FileReference.Combine(OutputDir, BaseFileName + ".cfg");
                FileItem      ConfigFileItem     = Graph.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 = Graph.CreateAction(ActionType.Compile);
                AnalyzeAction.CommandDescription = "Analyzing";
                AnalyzeAction.StatusDescription  = BaseFileName;
                AnalyzeAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory;
                AnalyzeAction.CommandPath        = AnalyzerFile;
                AnalyzeAction.CommandArguments   = String.Format("--cl-params \"{0}\" --source-file \"{1}\" --output-file \"{2}\" --cfg \"{3}\" --analysis-mode {4}", PreprocessAction.CommandArguments, SourceFileItem.AbsolutePath, OutputFileLocation, ConfigFileItem.AbsolutePath, (uint)Settings.ModeFlags);
                if (LicenseFile != null)
                {
                    AnalyzeAction.CommandArguments += String.Format(" --lic-file \"{0}\"", LicenseFile);
                    AnalyzeAction.PrerequisiteItems.Add(FileItem.GetItemByFileReference(LicenseFile));
                }
                AnalyzeAction.PrerequisiteItems.Add(ConfigFileItem);
                AnalyzeAction.PrerequisiteItems.Add(PreprocessedFileItem);
                AnalyzeAction.PrerequisiteItems.AddRange(InputFiles);          // Add the InputFiles as PrerequisiteItems so that in SingleFileCompile mode the PVSAnalyze step is not filtered out
                AnalyzeAction.ProducedItems.Add(OutputFileItem);
                AnalyzeAction.DeleteItems.Add(OutputFileItem);                 // PVS Studio will append by default, so need to delete produced items

                Result.ObjectFiles.AddRange(AnalyzeAction.ProducedItems);
            }
            return(Result);
        }
        public override CPPOutput CompileRCFiles(CppCompileEnvironment CompileEnvironment, List <FileItem> InputFiles, DirectoryReference OutputDir, ActionGraph ActionGraph)
        {
            CPPOutput Result = new CPPOutput();

            return(Result);
        }
		public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
		{
			if (Arches.Count == 0)
			{
				throw new BuildException("At least one architecture (armv7, x86, etc) needs to be selected in the project settings to build");
			}

			if (!bHasPrintedApiLevel)
			{
				Console.WriteLine("Compiling Native code with NDK API '{0}'", GetNdkApiLevel());
				bHasPrintedApiLevel = true;
			}

			string BaseArguments = "";

			if (CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create)
			{
				BaseArguments += " -Werror";

			}

			// Directly added NDK files for NDK extensions
			ConditionallyAddNDKSourceFiles(SourceFiles, ModuleName);

			// Deal with dynamic modules removed by architecture
			GenerateEmptyLinkFunctionsForRemovedModules(SourceFiles, ModuleName, CompileEnvironment.Config.OutputDirectory);

			// Add preprocessor definitions to the argument list.
			foreach (string Definition in CompileEnvironment.Config.Definitions)
			{
				BaseArguments += string.Format(" -D \"{0}\"", Definition);
			}

			var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);
			var NDKRoot = Environment.GetEnvironmentVariable("NDKROOT").Replace("\\", "/");

			string BasePCHName = "";
			var PCHExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Android].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
			if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
			{
				BasePCHName = RemoveArchName(CompileEnvironment.PrecompiledHeaderFile.AbsolutePath).Replace(PCHExtension, "");
			}

			// Create a compile action for each source file.
			CPPOutput Result = new CPPOutput();
			foreach (string Arch in Arches)
			{
				if (ShouldSkipModule(ModuleName, Arch))
				{
					continue;
				}

				foreach (string GPUArchitecture in GPUArchitectures)
				{
					// which toolchain to use
					string Arguments = GetCLArguments_Global(CompileEnvironment, Arch) + BaseArguments;

					switch (Arch)
					{
						case "-armv7":	Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_ARM=1"; break;
						case "-arm64":	Arguments += " -DPLATFORM_64BITS=1 -DPLATFORM_ANDROID_ARM64=1"; break;
						case "-x86":	Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_X86=1"; break;
						case "-x64":	Arguments += " -DPLATFORM_64BITS=1 -DPLATFORM_ANDROID_X64=1"; break;
						default:		Arguments += " -DPLATFORM_64BITS=0 -DPLATFORM_ANDROID_ARM=1"; break;
					}

					if (GPUArchitecture == "-gl4")
					{
						Arguments += " -DPLATFORM_ANDROIDGL4=1";
					}
					else if (GPUArchitecture == "-es31")
					{
						Arguments += " -DPLATFORM_ANDROIDES31=1";
					}

					// which PCH file to include
					string PCHArguments = "";
					if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
					{
						// Add the precompiled header file's path to the include path so Clang can find it.
						// This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
						PCHArguments += string.Format(" -include \"{0}\"", InlineArchName(BasePCHName, Arch, GPUArchitecture));
					}

					// Add include paths to the argument list (filtered by architecture)
					foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
					{
						if (IsDirectoryForArch(IncludePath, Arch))
						{
							Arguments += string.Format(" -I\"{0}\"", IncludePath);
						}
					}
					foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
					{
						if (IsDirectoryForArch(IncludePath, Arch))
						{
							Arguments += string.Format(" -I\"{0}\"", IncludePath);
						}
					}

					foreach (FileItem SourceFile in SourceFiles)
					{
						Action CompileAction = new Action(ActionType.Compile);
						string FileArguments = "";
						bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";
						bool bDisableShadowWarning = false;

						// should we disable optimizations on this file?
						// @todo android - We wouldn't need this if we could disable optimizations per function (via pragma)
						bool bDisableOptimizations = false;// SourceFile.AbsolutePath.ToUpperInvariant().IndexOf("\\SLATE\\") != -1;
						if (bDisableOptimizations && CompileEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Debug)
						{
							Log.TraceWarning("Disabling optimizations on {0}", SourceFile.AbsolutePath);
						}

						bDisableOptimizations = bDisableOptimizations || CompileEnvironment.Config.Target.Configuration == CPPTargetConfiguration.Debug;

						// Add C or C++ specific compiler arguments.
						if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
						{
							FileArguments += GetCompileArguments_PCH(bDisableOptimizations);
						}
						else if (bIsPlainCFile)
						{
							FileArguments += GetCompileArguments_C(bDisableOptimizations);

							// remove shadow variable warnings for NDK files
							if (SourceFile.AbsolutePath.Replace("\\", "/").StartsWith(NDKRoot))
							{
								bDisableShadowWarning = true;
							}
						}
						else
						{
							FileArguments += GetCompileArguments_CPP(bDisableOptimizations);

							// only use PCH for .cpp files
							FileArguments += PCHArguments;
						}

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

						if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
						{
							// Add the precompiled header file to the produced item list.
							FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
								Path.Combine(
									CompileEnvironment.Config.OutputDirectory,
									Path.GetFileName(InlineArchName(SourceFile.AbsolutePath, Arch, GPUArchitecture) + PCHExtension)
									)
								);

							CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
							Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

							// Add the parameters needed to compile the precompiled header file to the command-line.
							FileArguments += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
						}
						else
						{
							if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
							{
								CompileAction.bIsUsingPCH = true;
								FileItem ArchPrecompiledHeaderFile = FileItem.GetItemByPath(InlineArchName(BasePCHName, Arch, GPUArchitecture) + PCHExtension);
								CompileAction.PrerequisiteItems.Add(ArchPrecompiledHeaderFile);
							}

							var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Android].GetBinaryExtension(UEBuildBinaryType.Object);

							// Add the object file to the produced item list.
							FileItem ObjectFile = FileItem.GetItemByPath(
								InlineArchName( Path.Combine(
									CompileEnvironment.Config.OutputDirectory,
									Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension), Arch, GPUArchitecture
									)
								);
							CompileAction.ProducedItems.Add(ObjectFile);
							Result.ObjectFiles.Add(ObjectFile);

							FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
						}

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

						// Build a full argument list
						string AllArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
						AllArguments = ActionThread.ExpandEnvironmentVariables(AllArguments);
						AllArguments = AllArguments.Replace("\\", "/");

						// Remove shadow warning for this file if requested
						if (bDisableShadowWarning)
						{
							int WarningIndex = AllArguments.IndexOf(" -Wshadow");
							if (WarningIndex > 0)
							{
								AllArguments = AllArguments.Remove(WarningIndex, 9);
							}
						}

						// Create the response file
						string ResponseFileName = CompileAction.ProducedItems[0].AbsolutePath + ".response";
						string ResponseArgument = string.Format("@\"{0}\"", ResponseFile.Create(ResponseFileName, new List<string> { AllArguments }));

						CompileAction.WorkingDirectory = Path.GetFullPath(".");
						CompileAction.CommandPath = ClangPath;
						CompileAction.CommandArguments = ResponseArgument;
						CompileAction.StatusDescription = string.Format("{0} [{1}-{2}]", Path.GetFileName(SourceFile.AbsolutePath), Arch.Replace("-", ""), GPUArchitecture.Replace("-", ""));

						CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

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

			return Result;
		}
Exemple #42
0
        public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            string Arguments = GetCLArguments_Global(CompileEnvironment);
            string PCHArguments = "";

            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                // Add the precompiled header file's path to the include path so Clang can find it.
                // This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
				var PrecompiledFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
                PCHArguments += string.Format(" -include \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(PrecompiledFileExtension, ""));
            }

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D \"{0}\"", Definition);
            }

			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);
                string FileArguments = "";
                string Extension = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant();

                // Add C or C++ specific compiler arguments.
                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    FileArguments += GetCompileArguments_PCH();
                }
                else if (Extension == ".C")
                {
                    // Compile the file as C code.
                    FileArguments += GetCompileArguments_C();
                }
                else if (Extension == ".CC")
                {
                    // Compile the file as C++ code.
                    FileArguments += GetCompileArguments_CPP();
                }
                else if (Extension == ".MM")
                {
                    // Compile the file as Objective-C++ code.
                    FileArguments += GetCompileArguments_MM();
                }
                else if (Extension == ".M")
                {
                    // Compile the file as Objective-C code.
                    FileArguments += GetCompileArguments_M();
                }
                else
                {
                    FileArguments += GetCompileArguments_CPP();

                    // only use PCH for .cpp files
                    FileArguments += PCHArguments;
                }

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

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
					var PrecompiledFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader);
                    // Add the precompiled header file to the produced item list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.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 += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                    }

					var ObjectFileExtension = UEBuildPlatform.BuildPlatformDictionary[UnrealTargetPlatform.Linux].GetBinaryExtension(UEBuildBinaryType.Object);
                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);

                    FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
                }

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

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                if (!UsingClang())
                {
                    CompileAction.CommandPath = GCCPath;
                }
                else
                {
                    CompileAction.CommandPath = ClangPath;
                }
                CompileAction.CommandArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                CompileAction.CommandDescription = "Compile";
                CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath);
                CompileAction.bIsGCCCompiler = true;

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

                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);
            }

            return Result;
        }
        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);
        }
        public override CPPOutput CompileCPPFiles(CPPEnvironment CompileEnvironment, List<FileItem> SourceFiles, string ModuleName)
        {
            if (!bHasPrintedApiLevel)
            {
                Console.WriteLine("Compiling with NDK API '{0}'", GetNdkApiLevel());
                bHasPrintedApiLevel = true;
            }

            string Arguments = GetCLArguments_Global(CompileEnvironment);
            string PCHArguments = "";

            if (CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create)
            {
                Arguments += " -Werror";

            }
            if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
            {
                // Add the precompiled header file's path to the include path so Clang can find it.
                // This needs to be before the other include paths to ensure Clang uses it instead of the source header file.
                PCHArguments += string.Format(" -include \"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath.Replace(".gch", ""));
            }

            // Add include paths to the argument list.
            foreach (string IncludePath in CompileEnvironment.Config.SystemIncludePaths)
            {
                Arguments += string.Format(" -I\"{0}\"", IncludePath);
            }
            foreach (string IncludePath in CompileEnvironment.Config.IncludePaths)
            {
                // we make this absolute because there are some edge cases when a code-based rocket project on the same dtive
                // as the engine will make relative paths that make clang fail to compile. Absolute will succeeed.
                Arguments += string.Format(" -I\"{0}\"", Path.GetFullPath(IncludePath));
            }

            // Directly added NDK files for NDK extensions
            if (!UnrealBuildTool.RunningRocket())
            {
                ConditionallyAddNDKSourceFiles(SourceFiles);
            }

            // Add preprocessor definitions to the argument list.
            foreach (string Definition in CompileEnvironment.Config.Definitions)
            {
                Arguments += string.Format(" -D \"{0}\"", Definition);
            }

            // Create a compile action for each source file.
            CPPOutput Result = new CPPOutput();
            foreach (FileItem SourceFile in SourceFiles)
            {
                Action CompileAction = new Action(ActionType.Compile);
                string FileArguments = "";
                bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C";

                // should we disable optimizations on this file?
                // @todo android - We wouldn't need this if we could disable optimizations per function (via pragma)
                bool bDisableOptimizations = false;// SourceFile.AbsolutePath.ToUpperInvariant().IndexOf("\\SLATE\\") != -1;
                if (bDisableOptimizations && CompileEnvironment.Config.TargetConfiguration != CPPTargetConfiguration.Debug)
                {
                    Log.TraceWarning("Disabling optimizations on {0}", SourceFile.AbsolutePath);
                }

                bDisableOptimizations = bDisableOptimizations || CompileEnvironment.Config.TargetConfiguration == CPPTargetConfiguration.Debug;

                // Add C or C++ specific compiler arguments.
                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    FileArguments += GetCompileArguments_PCH(bDisableOptimizations);
                }
                else if (bIsPlainCFile)
                {
                    FileArguments += GetCompileArguments_C(bDisableOptimizations);
                }
                else
                {
                    FileArguments += GetCompileArguments_CPP(bDisableOptimizations);

                    // only use PCH for .cpp files
                    FileArguments += PCHArguments;
                }

                // Add the C++ source file and its included files to the prerequisite item list.
                CompileAction.PrerequisiteItems.Add(SourceFile);
                foreach (FileItem IncludedFile in CompileEnvironment.GetIncludeDependencies(SourceFile))
                {
                    CompileAction.PrerequisiteItems.Add(IncludedFile);
                }

                if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create)
                {
                    // Add the precompiled header file to the produced item list.
                    FileItem PrecompiledHeaderFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".gch"
                            )
                        );

                    CompileAction.ProducedItems.Add(PrecompiledHeaderFile);
                    Result.PrecompiledHeaderFile = PrecompiledHeaderFile;

                    // Add the parameters needed to compile the precompiled header file to the command-line.
                    FileArguments += string.Format(" -o \"{0}\"", PrecompiledHeaderFile.AbsolutePath, false);
                }
                else
                {
                    if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include)
                    {
                        CompileAction.bIsUsingPCH = true;
                        CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile);
                    }

                    // Add the object file to the produced item list.
                    FileItem ObjectFile = FileItem.GetItemByPath(
                        Path.Combine(
                            CompileEnvironment.Config.OutputDirectory,
                            Path.GetFileName(SourceFile.AbsolutePath) + ".o"
                            )
                        );
                    CompileAction.ProducedItems.Add(ObjectFile);
                    Result.ObjectFiles.Add(ObjectFile);

                    FileArguments += string.Format(" -o \"{0}\"", ObjectFile.AbsolutePath, false);
                }

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

                // Build a full argument list
                string AllArguments = Arguments + FileArguments + CompileEnvironment.Config.AdditionalArguments;
                AllArguments = ActionThread.ExpandEnvironmentVariables(AllArguments);
                AllArguments = AllArguments.Replace("\\", "/");

                // Create the response file
                string ResponseFileName = CompileAction.ProducedItems[0].AbsolutePath + ".response";
                string ResponseArgument = string.Format("@\"{0}\"", ResponseFile.Create(ResponseFileName, new List<string>{ AllArguments } ));

                CompileAction.WorkingDirectory = Path.GetFullPath(".");
                CompileAction.CommandPath = ClangPath;
                CompileAction.CommandArguments = ResponseArgument;
                CompileAction.StatusDescription = string.Format("{0}", Path.GetFileName(SourceFile.AbsolutePath));
                CompileAction.StatusDetailedDescription = SourceFile.Description;

                CompileAction.OutputEventHandler = new DataReceivedEventHandler(CompileOutputReceivedDataEventHandler);

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

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

            return Result;
        }