// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; using Tools.DotNETCommon; namespace UnrealBuildTool { /// /// Base class for platform-specific project generators /// class AndroidProjectGenerator : PlatformProjectGenerator { bool CheckedForNsight = false; // whether we have checked for a recent enough version of Nsight yet bool NsightInstalled = false; // true if a recent enough version of Nsight is installed int NsightVersionCode = 0; // version code matching detected Nsight bool VSDebugCommandLineOptionPresent = false; //User must put -vsdebugandroid commandline option to build the debug projects bool VSDebuggingEnabled = false; // When set to true, allows debugging with built in MS Cross Platform Android tools. // It adds separate projects ending in .androidproj and a file VSAndroidUnreal.props for the engine and all game projects bool VSSupportChecked = false; // Don't want to check multiple times bool VSPropsFileWritten = false; // This is for the file VSAndroidUnreal.props which only needs to be written once bool VSSandboxedSDK = false; // Checks if VS has installed the sandboxed SDK version to support Unreal // If this sandboxed SDK is present change the config to consume it instead of the main VS Android SDK public AndroidProjectGenerator(CommandLineArguments Arguments) : base(Arguments) { if (Arguments.HasOption("-vsdebugandroid")) { VSDebugCommandLineOptionPresent = true; } } bool IsVSAndroidSupportInstalled() { if (VSSupportChecked) { return VSDebuggingEnabled; } VSSupportChecked = true; //check to make sure Cross Platform Tools are installed for MS // First check to see if the sandboxed SDK has been installed, it's always dropped to the same ProgramData file location if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Microsoft\\AndroidSDK\\25\\tools\\android.bat")) && VSDebugCommandLineOptionPresent) { VSDebuggingEnabled = true; VSSandboxedSDK = true; } else { // If the sandboxed SDK is not present (pre Visual Studio 15.4) then the non-Sandboxed SDK tools should have the correct build tools for building string SDKToolsPath = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Android SDK Tools", "Path", null) as string; if (!String.IsNullOrEmpty(SDKToolsPath) && VSDebugCommandLineOptionPresent) { VSDebuggingEnabled = true; } } if (VSDebugCommandLineOptionPresent && VSDebuggingEnabled == false) { Log.TraceWarning("Android SDK tools have to be installed to use this. Please Install Visual C++ for Cross-Platform Mobile Development https://msdn.microsoft.com/en-us/library/dn707598.aspx"); } return VSDebuggingEnabled; } /// /// Check to see if a recent enough version of Nsight is installed. /// bool IsNsightInstalled(VCProjectFileFormat ProjectFileFormat) { // cache the results since this gets called a number of times if (CheckedForNsight) { return NsightInstalled; } CheckedForNsight = true; // NOTE: there is now a registry key that we can use instead at: // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\NVIDIA Corporation\Nsight Tegra\Version string ProgramFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); string PlatformToolsetVersion = VCProjectFileGenerator.GetProjectFilePlatformToolsetVersionString(ProjectFileFormat); if (String.IsNullOrEmpty(PlatformToolsetVersion)) { // future maintainer: add toolset version and verify that the rest of the msbuild path, version, and location in ProgramFiles(x86) is still valid Log.TraceInformation("Android project generation needs to be updated for this version of Visual Studio."); return false; } // build the path to where the Nsight DLL we'll be checking should sit string NsightDllPath = Path.Combine(ProgramFilesPath, @"MSBuild\Microsoft.Cpp\v4.0", PlatformToolsetVersion, @"Platforms\Tegra-Android\Nvidia.Build.CPPTasks.Tegra-Android.Extensibility.dll"); if (!File.Exists(NsightDllPath)) { return false; } // grab the version info from the DLL FileVersionInfo NsightVersion = FileVersionInfo.GetVersionInfo(NsightDllPath); if (NsightVersion.ProductMajorPart > 3) { // Mark as Nsight 3.1 (project will be updated) NsightVersionCode = 11; NsightInstalled = true; } else if (NsightVersion.ProductMajorPart == 3) { // Nsight 3.0 supported NsightVersionCode = 9; NsightInstalled = true; if (NsightVersion.ProductMinorPart >= 1) { // Nsight 3.1+ should be valid (will update project if newer) NsightVersionCode = 11; } } else if (NsightVersion.ProductMajorPart == 2) { // Nsight 2.0+ should be valid NsightVersionCode = 6; NsightInstalled = true; } else if ((NsightVersion.ProductMajorPart == 1) && (NsightVersion.ProductMinorPart >= 5)) { // Nsight 1.5+ should be valid NsightVersionCode = 6; NsightInstalled = true; } if (!NsightInstalled) { Log.TraceInformation("\nNsight Tegra {0}.{1} found, but Nsight Tegra 1.5 or higher is required for debugging support.", NsightVersion.ProductMajorPart, NsightVersion.ProductMinorPart); } return NsightInstalled; } /// /// Enumerate all the platforms that this generator supports /// public override IEnumerable GetPlatforms() { yield return UnrealTargetPlatform.Android; } /// /// Whether this build platform has native support for VisualStudio /// /// The UnrealTargetPlatform being built /// The UnrealTargetConfiguration being built /// /// bool true if native VisualStudio support (or custom VSI) is available public override bool HasVisualStudioSupport(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, VCProjectFileFormat ProjectFileFormat) { // Debugging, etc. are dependent on the TADP being installed return IsNsightInstalled(ProjectFileFormat) || IsVSAndroidSupportInstalled(); } /// /// Return the VisualStudio platform name for this build platform /// /// The UnrealTargetPlatform being built /// The UnrealTargetConfiguration being built /// string The name of the platform that VisualStudio recognizes public override string GetVisualStudioPlatformName(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration) { string PlatformName = InPlatform.ToString(); if (InPlatform == UnrealTargetPlatform.Android) { if (IsVSAndroidSupportInstalled()) { PlatformName = "ARM"; } else { PlatformName = "Tegra-Android"; } } return PlatformName; } /// /// Return any custom property group lines /// /// The UnrealTargetPlatform being built /// /// String builder for the project file /// string The custom property import lines for the project file; Empty string if it doesn't require one public override void GetAdditionalVisualStudioPropertyGroups(UnrealTargetPlatform InPlatform, VCProjectFileFormat ProjectFileFormat, StringBuilder ProjectFileBuilder) { if(IsVSAndroidSupportInstalled() || !IsNsightInstalled(ProjectFileFormat)) { base.GetAdditionalVisualStudioPropertyGroups(InPlatform, ProjectFileFormat, ProjectFileBuilder); } else { ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" " + NsightVersionCode.ToString() + ""); ProjectFileBuilder.AppendLine(" "); } } /// /// Return any custom property group lines /// /// The UnrealTargetPlatform being built /// /// string The custom property import lines for the project file; Empty string if it doesn't require one public override string GetVisualStudioPlatformConfigurationType(UnrealTargetPlatform InPlatform, VCProjectFileFormat ProjectFileFormat) { string ConfigurationType = ""; if(IsVSAndroidSupportInstalled()) { ConfigurationType = "Makefile"; } else if (IsNsightInstalled(ProjectFileFormat)) { ConfigurationType = "ExternalBuildSystem"; } else { ConfigurationType = base.GetVisualStudioPlatformConfigurationType(InPlatform, ProjectFileFormat); } return ConfigurationType; } /// /// Return the platform toolset string to write into the project configuration /// /// The UnrealTargetPlatform being built /// The UnrealTargetConfiguration being built /// The version of Visual Studio to target /// String builder for the project file /// string The custom configuration section for the project file; Empty string if it doesn't require one public override void GetVisualStudioPlatformToolsetString(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { if (IsVSAndroidSupportInstalled() || !IsNsightInstalled(InProjectFileFormat)) { ProjectFileBuilder.AppendLine(" " + VCProjectFileGenerator.GetProjectFilePlatformToolsetVersionString(InProjectFileFormat) + ""); } else { ProjectFileBuilder.AppendLine(" " + VCProjectFileGenerator.GetProjectFilePlatformToolsetVersionString(InProjectFileFormat) + ""); ProjectFileBuilder.AppendLine(" UseTarget"); } } /// /// Return any custom paths for VisualStudio this platform requires /// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath. /// /// The UnrealTargetPlatform being built /// The configuration being built /// The type of target (game or program) /// Path to the target.cs file /// Path to the project file /// /// Format for the generated project files /// String builder for the project file /// The custom path lines for the project file; Empty string if it doesn't require one public override void GetVisualStudioPathsEntries(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { if (!IsVSAndroidSupportInstalled() && IsNsightInstalled(InProjectFileFormat)) { // NOTE: We are intentionally overriding defaults for these paths with empty strings. We never want Visual Studio's // defaults for these fields to be propagated, since they are version-sensitive paths that may not reflect // the environment that UBT is building in. We'll set these environment variables ourselves! // NOTE: We don't touch 'ExecutablePath' because that would result in Visual Studio clobbering the system "Path" // environment variable //@todo android: clean up debug path generation string GameName = TargetRulesPath.GetFileNameWithoutExtension(); GameName = Path.GetFileNameWithoutExtension(GameName); // intermediate path for Engine or Game's intermediate string IntermediateDirectoryPath; IntermediateDirectoryPath = Path.GetDirectoryName(NMakeOutputPath.FullName) + "/../../Intermediate/Android/APK"; // string for string APKPath = Path.Combine( Path.GetDirectoryName(NMakeOutputPath.FullName), Path.GetFileNameWithoutExtension(NMakeOutputPath.FullName) + "-armv7-es2.apk"); // string for and string BuildXmlPath = IntermediateDirectoryPath; string AndroidManifestPath = Path.Combine(IntermediateDirectoryPath, "AndroidManifest.xml"); // string for string AdditionalLibDirs = ""; AdditionalLibDirs += IntermediateDirectoryPath + @"\obj\local\armeabi-v7a"; AdditionalLibDirs += ";" + IntermediateDirectoryPath + @"\obj\local\x86"; AdditionalLibDirs += @";$(AdditionalLibraryDirectories)"; ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" "); ProjectFileBuilder.AppendLine(" False"); ProjectFileBuilder.AppendLine(" AndroidDebugger"); ProjectFileBuilder.AppendLine(" " + APKPath + ""); ProjectFileBuilder.AppendLine(" " + AdditionalLibDirs + ""); ProjectFileBuilder.AppendLine(" " + BuildXmlPath + ""); ProjectFileBuilder.AppendLine(" " + AndroidManifestPath + ""); } else { base.GetVisualStudioPathsEntries(InPlatform, InConfiguration, TargetType, TargetRulesPath, ProjectFilePath, NMakeOutputPath, InProjectFileFormat, ProjectFileBuilder); } } /// /// Return any custom property settings. These will be included right after Global properties to make values available to all other imports. /// /// The UnrealTargetPlatform being built /// String builder for the project file /// string The custom property import lines for the project file; Empty string if it doesn't require one public override void GetVisualStudioGlobalProperties(UnrealTargetPlatform InPlatform, StringBuilder ProjectFileBuilder) { if (IsVSAndroidSupportInstalled()) { ProjectFileBuilder.AppendLine(" "); } else { base.GetVisualStudioGlobalProperties(InPlatform, ProjectFileBuilder); } } /// /// Return any custom property settings. These will be included in the ImportGroup section /// /// The UnrealTargetPlatform being built /// String builder for the project file /// string The custom property import lines for the project file; Empty string if it doesn't require one public override void GetVisualStudioImportGroupProperties(UnrealTargetPlatform InPlatform, StringBuilder ProjectFileBuilder) { if (IsVSAndroidSupportInstalled()) { ProjectFileBuilder.AppendLine(" "); } else { base.GetVisualStudioImportGroupProperties(InPlatform, ProjectFileBuilder); } } /// /// For Additional Project Property file VSAndroidUnreal.props file that need to be written out. This is currently used only on Android. /// public override void WriteAdditionalPropFile() { if(!IsVSAndroidSupportInstalled()) { return; } //This file only needs to be written once and doesn't change. if(VSPropsFileWritten) { return; } VSPropsFileWritten = true; string FileName = "VSAndroidUnreal.props"; // Change the path to the Android SDK based on if we are using the Visual Studio Sandboxed SDK or not string vsAndroidSDKPath; if (VSSandboxedSDK) { vsAndroidSDKPath = "$(ProgramData)\\Microsoft\\AndroidSDK\\25"; } else { vsAndroidSDKPath = "$(VS_AndroidHome)"; } string FileText = "" + ProjectFileGenerator.NewLine + "" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + vsAndroidSDKPath + "" + ProjectFileGenerator.NewLine + " $(VS_JavaHome)" + ProjectFileGenerator.NewLine + " $(VS_AntHome)" + ProjectFileGenerator.NewLine + " $(VS_NdkRoot)" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " $(ANDROID_HOME)" + ProjectFileGenerator.NewLine + " true" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " $(JAVA_HOME)" + ProjectFileGenerator.NewLine + " true" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " $(ANT_HOME)" + ProjectFileGenerator.NewLine + " true" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " $(NDKROOT)" + ProjectFileGenerator.NewLine + " true" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + ""; ProjectFileGenerator.WriteFileIfChanged(ProjectFileGenerator.IntermediateProjectFilesPath + "\\" + FileName, FileText); } /// /// For additional Project file *PROJECTNAME*-AndroidRun.androidproj.user that needs to be written out. This is currently used only on Android. /// /// ProjectFile object public override void WriteAdditionalProjUserFile(ProjectFile ProjectFile) { if (!IsVSAndroidSupportInstalled() || ProjectFile.SourceFiles.Count == 0) { return; } string BaseDirectory = ProjectFile.SourceFiles[0].BaseFolder.FullName; string ProjectName = ProjectFile.ProjectFilePath.GetFileNameWithoutExtension(); string FileName = ProjectName + "-AndroidRun.androidproj.user"; string FileText = "" + ProjectFileGenerator.NewLine + "" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + BaseDirectory + "\\Binaries\\Android\\" + ProjectName + "-armv7-es2.apk" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + BaseDirectory + "\\Intermediate\\Android\\APK\\obj\\local\\armeabi-v7a;" + BaseDirectory + "\\Intermediate\\Android\\APK\\jni\\armeabi-v7a;" + BaseDirectory + "\\Binaries\\Android;$(AdditionalSymbolSearchPaths)" + ProjectFileGenerator.NewLine + " AndroidDebugger" + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + ""; ProjectFileGenerator.WriteFileIfChanged(ProjectFileGenerator.IntermediateProjectFilesPath + "\\" + FileName, FileText); } /// /// For additional Project file *PROJECTNAME*-AndroidRun.androidproj that needs to be written out. This is currently used only on Android. /// /// ProjectFile object public override Tuple WriteAdditionalProjFile(ProjectFile ProjectFile) { if (!IsVSAndroidSupportInstalled()) { return null; } string ProjectName = ProjectFile.ProjectFilePath.GetFileNameWithoutExtension() + "-AndroidRun"; string FileName = ProjectName + ".androidproj"; string FileText = " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Debug " + ProjectFileGenerator.NewLine + " ARM " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Development " + ProjectFileGenerator.NewLine + " ARM " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Release " + ProjectFileGenerator.NewLine + " ARM " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Debug " + ProjectFileGenerator.NewLine + " ARM64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Development " + ProjectFileGenerator.NewLine + " ARM64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Release " + ProjectFileGenerator.NewLine + " ARM64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Debug " + ProjectFileGenerator.NewLine + " x64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Development " + ProjectFileGenerator.NewLine + " x64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Release " + ProjectFileGenerator.NewLine + " x64 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Debug " + ProjectFileGenerator.NewLine + " x86 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Development " + ProjectFileGenerator.NewLine + " x86 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " Release " + ProjectFileGenerator.NewLine + " x86 " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectName + " " + ProjectFileGenerator.NewLine + " 14.0 " + ProjectFileGenerator.NewLine + " 1.0 " + ProjectFileGenerator.NewLine + //Set the project guid " " + System.Guid.NewGuid().ToString("B").ToUpper() + " " + ProjectFileGenerator.NewLine + " Application " + ProjectFileGenerator.NewLine + " <_PackagingProjectWithoutNativeComponent>true " + ProjectFileGenerator.NewLine + " com." + ProjectName + "." + ProjectName + " " + ProjectFileGenerator.NewLine + " src " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " true " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " true " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " true " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " true " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " false " + ProjectFileGenerator.NewLine + " $(RootNamespace) " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + " " + ProjectFileGenerator.NewLine + ""; bool Success = ProjectFileGenerator.WriteFileIfChanged(ProjectFileGenerator.IntermediateProjectFilesPath + "\\" + FileName, FileText); FileReference ProjectFilePath = FileReference.Combine(ProjectFileGenerator.IntermediateProjectFilesPath, FileName); AndroidDebugProjectFile Project = new AndroidDebugProjectFile(ProjectFilePath); Project.ShouldBuildForAllSolutionTargets = false; Project.ShouldBuildByDefaultForSolutionTargets = false; return Success ? new Tuple(Project, "UE4 Android Debug Projects") : null; } } /// /// An Android Debug Project /// class AndroidDebugProjectFile : MSBuildProjectFile { /// /// Constructs a new project file object /// /// The path to the project file on disk public AndroidDebugProjectFile(FileReference InitFilePath) : base(InitFilePath) { } /// /// This is the GUID that Visual Studio uses to identify an Android project file in the solution /// public override string ProjectTypeGUID { get { return "{39E2626F-3545-4960-A6E8-258AD8476CE5}"; } } /// /// The only valid configuration for these to be run in is Debug|ARM /// /// The solution target type /// The solution configuration /// The solution platform /// Set of platform project generators /// Project context matching the given solution context public override MSBuildProjectContext GetMatchingProjectContext(TargetType SolutionTarget, UnrealTargetConfiguration SolutionConfiguration, UnrealTargetPlatform SolutionPlatform, PlatformProjectGeneratorCollection PlatformProjectGenerators) { return new MSBuildProjectContext("Debug", "ARM"){ bBuildByDefault = (SolutionPlatform == UnrealTargetPlatform.Android) }; } } }