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;
		}
Пример #2
0
        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);
        }