public static bool ValidateNdkPlatform(TaskLoggingHelper log, string ndkPath, AndroidTargetArch arch, bool enableLLVM) { // Check that we have a compatible NDK version for the targeted ABIs. NdkUtil.NdkVersion ndkVersion; bool hasNdkVersion = NdkUtil.GetNdkToolchainRelease(ndkPath, out ndkVersion); if (NdkUtil.IsNdk64BitArch(arch) && hasNdkVersion && ndkVersion.Version < 10) { log.LogMessage(MessageImportance.High, "The detected Android NDK version is incompatible with the targeted 64-bit architecture, " + "please upgrade to NDK r10 or newer."); } // NDK r10d is buggy and cannot link x86_64 ABI shared libraries because they are 32-bits. // See https://code.google.com/p/android/issues/detail?id=161421 if (enableLLVM && ndkVersion.Version == 10 && ndkVersion.Revision == "d" && arch == AndroidTargetArch.X86_64) { log.LogCodedError("XA3004", "Android NDK r10d is buggy and provides an incompatible x86_64 libm.so. " + "See https://code.google.com/p/android/issues/detail?id=161422."); return(false); } if (enableLLVM && (ndkVersion.Version < 10 || (ndkVersion.Version == 10 && ndkVersion.Revision[0] < 'd'))) { log.LogCodedError("XA3005", "The detected Android NDK version is incompatible with the targeted LLVM configuration, " + "please upgrade to NDK r10d or newer."); } return(true); }
static bool ValidateAotConfiguration(TaskLoggingHelper log, AndroidTargetArch arch, bool enableLLVM) { if (arch == AndroidTargetArch.Arm64 && enableLLVM) { log.LogCodedError("XA3004", "arm64-v8a architecture is not currently supported on LLVM AOT mode."); return(false); } if (arch == AndroidTargetArch.X86_64) { log.LogCodedError("XA3004", "x86_64 architecture is not currently supported on AOT mode."); return(false); } return(true); }
public static string TryGetAndroidJarPath(TaskLoggingHelper log, string platform) { var platformPath = MonoAndroidHelper.AndroidSdk.TryGetPlatformDirectoryFromApiLevel(platform, MonoAndroidHelper.SupportedVersions); if (platformPath == null) { var expectedPath = MonoAndroidHelper.AndroidSdk.GetPlatformDirectoryFromId(platform); var sdkManagerMenuPath = OS.IsWindows ? Properties.Resources.XA5207_SDK_Manager_Windows : Properties.Resources.XA5207_SDK_Manager_macOS; log.LogCodedError("XA5207", Properties.Resources.XA5207, platform, Path.Combine(expectedPath, "android.jar"), sdkManagerMenuPath); return(null); } return(Path.Combine(platformPath, "android.jar")); }
public static string TryGetAndroidJarPath(TaskLoggingHelper log, string platform) { var platformPath = MonoAndroidHelper.AndroidSdk.TryGetPlatformDirectoryFromApiLevel(platform, MonoAndroidHelper.SupportedVersions); if (platformPath == null) { var expectedPath = MonoAndroidHelper.AndroidSdk.GetPlatformDirectoryFromId(platform); log.LogCodedError("XA5207", "Could not find android.jar for API Level {0}. " + "This means the Android SDK platform for API Level {0} is not installed. " + "Either install it in the Android SDK Manager (Tools > Open Android SDK Manager...), " + "or change your Xamarin.Android project to target an API version that is installed. " + "({1} missing.)", platform, Path.Combine(expectedPath, "android.jar")); return(null); } return(Path.Combine(platformPath, "android.jar")); }
public static bool Init(TaskLoggingHelper log, string ndkPath) { Version ndkVersion; bool hasNdkVersion = GetNdkToolchainRelease(ndkPath ?? "", out ndkVersion); if (!hasNdkVersion) { log.LogCodedError("XA5101", "Could not locate the Android NDK. Please make sure the Android NDK is installed in the Android SDK Manager, " + "or if using a custom NDK path, please ensure the $(AndroidNdkDirectory) MSBuild property is set to the custom path."); return(false); } usingClangNDK = ndkVersion.Major >= 19; return(true); }
public static void LogFromStandardError(this TaskLoggingHelper log, string defaultErrorCode, string message) { if (string.IsNullOrEmpty(message)) { return; } var m = Message.Match(message); if (!m.Success) { if (message.IndexOf("error:", StringComparison.InvariantCultureIgnoreCase) != -1) { log.LogCodedError(defaultErrorCode, message); } else { log.LogMessage(null, defaultErrorCode, null, null, 0, 0, 0, 0, MessageImportance.Low, message); } return; } string subcategory = m.Groups["source"].Value; string type = m.Groups["type"].Value; string code = m.Groups["code"].Value; string msg = m.Groups["message"].Value; if (string.IsNullOrEmpty(code)) { code = defaultErrorCode; } if (type == "warning") { log.LogWarning(subcategory, code, string.Empty, string.Empty, 0, 0, 0, 0, "{0}", msg); } else { log.LogError(subcategory, code, string.Empty, string.Empty, 0, 0, 0, 0, "{0}", msg); } }
public bool Run(Assembly assm, string ResourceName, string OutputPath, TaskLoggingHelper Log) { // Ensure our output directory exists if (!Directory.Exists(Path.GetDirectoryName(OutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(OutputPath)); } // Copy out one of our embedded resources to a path using (var from = GetManifestResourceStream(ResourceName)) { if (from == null) { Log.LogCodedError("XA0116", $"Unable to find `EmbeddedResource` of name `{ResourceName}`."); return(false); } // If the resource already exists, only overwrite if it's changed if (File.Exists(OutputPath)) { var hash1 = MonoAndroidHelper.HashFile(OutputPath); var hash2 = MonoAndroidHelper.HashStream(from); if (hash1 == hash2) { Log.LogDebugMessage("Resource {0} is unchanged. Skipping.", OutputPath); return(true); } } // Hash calculation read to the end, move back to beginning of file from.Position = 0; // Write out the resource using (var to = File.Create(OutputPath)) Copy(from, to); Log.LogDebugMessage("Wrote resource {0}.", OutputPath); } return(true); }
public static void LogUnhandledException(this TaskLoggingHelper log, string prefix, Exception ex) { prefix = "XA" + prefix; // Some ordering is necessary here to ensure exceptions are before their base exceptions if (ex is NullReferenceException) { log.LogCodedError(prefix + "7001", ex.ToString()); } else if (ex is ArgumentOutOfRangeException) // ArgumentException { log.LogCodedError(prefix + "7002", ex.ToString()); } else if (ex is ArgumentNullException) // ArgumentException { log.LogCodedError(prefix + "7003", ex.ToString()); } else if (ex is ArgumentException) { log.LogCodedError(prefix + "7004", ex.ToString()); } else if (ex is FormatException) { log.LogCodedError(prefix + "7005", ex.ToString()); } else if (ex is IndexOutOfRangeException) { log.LogCodedError(prefix + "7006", ex.ToString()); } else if (ex is InvalidCastException) { log.LogCodedError(prefix + "7007", ex.ToString()); } else if (ex is ObjectDisposedException) // InvalidOperationException { log.LogCodedError(prefix + "7008", ex.ToString()); } else if (ex is InvalidOperationException) { log.LogCodedError(prefix + "7009", ex.ToString()); } else if (ex is InvalidProgramException) { log.LogCodedError(prefix + "7010", ex.ToString()); } else if (ex is KeyNotFoundException) { log.LogCodedError(prefix + "7011", ex.ToString()); } else if (ex is TaskCanceledException) // OperationCanceledException { log.LogCodedError(prefix + "7012", ex.ToString()); } else if (ex is OperationCanceledException) { log.LogCodedError(prefix + "7013", ex.ToString()); } else if (ex is OutOfMemoryException) { log.LogCodedError(prefix + "7014", ex.ToString()); } else if (ex is NotSupportedException) { log.LogCodedError(prefix + "7015", ex.ToString()); } else if (ex is StackOverflowException) { log.LogCodedError(prefix + "7016", ex.ToString()); } else if (ex is TimeoutException) { log.LogCodedError(prefix + "7017", ex.ToString()); } else if (ex is TypeInitializationException) { log.LogCodedError(prefix + "7018", ex.ToString()); } else if (ex is UnauthorizedAccessException) { log.LogCodedError(prefix + "7019", ex.ToString()); } else if (ex is ApplicationException) { log.LogCodedError(prefix + "7020", ex.ToString()); } else if (ex is KeyNotFoundException) { log.LogCodedError(prefix + "7021", ex.ToString()); } else if (ex is PathTooLongException) // IOException { log.LogCodedError(prefix + "7022", ex.ToString()); } else if (ex is DirectoryNotFoundException) // IOException { log.LogCodedError(prefix + "7023", ex.ToString()); } else if (ex is DriveNotFoundException) // IOException { log.LogCodedError(prefix + "7025", ex.ToString()); } else if (ex is EndOfStreamException) // IOException { log.LogCodedError(prefix + "7026", ex.ToString()); } else if (ex is FileLoadException) // IOException { log.LogCodedError(prefix + "7027", ex.ToString()); } else if (ex is FileNotFoundException) // IOException { log.LogCodedError(prefix + "7028", ex.ToString()); } else if (ex is PipeException) // IOException { log.LogCodedError(prefix + "7029", ex.ToString()); } else if (ex is IOException) { log.LogCodedError(prefix + "7024", ex.ToString()); } log.LogCodedError(prefix + "7000", ex.ToString()); }
public static void FixupResourceFilenameAndLogCodedError(this TaskLoggingHelper log, string code, string message, string file, string resourceDir, Dictionary <string, string> resourceNameCaseMap) { var targetfile = FixupResourceFilename(file, resourceDir, resourceNameCaseMap); log.LogCodedError(code, file: targetfile, lineNumber: 0, message: message); }
public static bool ValidateNdkPlatform(TaskLoggingHelper log, string ndkPath, AndroidTargetArch arch, bool enableLLVM) { return(ValidateNdkPlatform((m) => log.LogMessage(m), (c, m) => log.LogCodedError(c, m), ndkPath, arch, enableLLVM)); }
public static bool Init(TaskLoggingHelper log, string ndkPath) => Init((c, m) => log.LogCodedError(c, m), ndkPath);
public static void LogUnhandledException(this TaskLoggingHelper log, string prefix, Exception ex) { LogUnhandledException((code, message) => log.LogCodedError(code, message), prefix, ex); }
public IList <string> Merge(List <TypeDefinition> subclasses, string applicationClass, bool embed, string bundledWearApplicationName, IEnumerable <string> mergedManifestDocuments) { string applicationName = ApplicationName; var manifest = doc.Root; if (manifest == null || manifest.Name != "manifest") { throw new Exception("Root element must be 'manifest'"); } var manifest_package = (string)manifest.Attribute("package"); if (!string.IsNullOrWhiteSpace(manifest_package)) { PackageName = manifest_package; } manifest.SetAttributeValue(XNamespace.Xmlns + "android", "http://schemas.android.com/apk/res/android"); if (manifest.Attribute(androidNs + "versionCode") == null) { manifest.SetAttributeValue(androidNs + "versionCode", "1"); } if (manifest.Attribute(androidNs + "versionName") == null) { manifest.SetAttributeValue(androidNs + "versionName", "1.0"); } app = CreateApplicationElement(manifest, applicationClass, subclasses); if (app.Attribute(androidNs + "label") == null && applicationName != null) { app.SetAttributeValue(androidNs + "label", applicationName); } var existingTypes = new HashSet <string> ( app.Descendants().Select(a => (string)a.Attribute(attName)).Where(v => v != null)); if (!string.IsNullOrEmpty(bundledWearApplicationName)) { if (!app.Elements("meta-data").Any(e => e.Attributes(androidNs + "name").Any(a => a.Value == bundledWearApplicationName))) { app.Add(new XElement("meta-data", new XAttribute(androidNs + "name", "com.google.android.wearable.beta.app"), new XAttribute(androidNs + "resource", "@xml/wearable_app_desc"))); } } // If no <uses-sdk> is specified, add it with both minSdkVersion and // targetSdkVersion set to TargetFrameworkVersion if (!manifest.Elements("uses-sdk").Any()) { manifest.AddFirst( new XElement("uses-sdk", new XAttribute(androidNs + "minSdkVersion", SdkVersionName), new XAttribute(androidNs + "targetSdkVersion", SdkVersionName))); } // If no minSdkVersion is specified, set it to TargetFrameworkVersion var uses = manifest.Element("uses-sdk"); if (uses.Attribute(androidNs + "minSdkVersion") == null) { int minSdkVersion; if (!int.TryParse(SdkVersionName, out minSdkVersion)) { minSdkVersion = XABuildConfig.NDKMinimumApiAvailable; } minSdkVersion = Math.Min(minSdkVersion, XABuildConfig.NDKMinimumApiAvailable); uses.SetAttributeValue(androidNs + "minSdkVersion", minSdkVersion.ToString()); } string targetSdkVersion; var tsv = uses.Attribute(androidNs + "targetSdkVersion"); if (tsv != null) { targetSdkVersion = tsv.Value; } else { targetSdkVersion = SdkVersionName; uses.AddBeforeSelf(new XComment("suppress UsesMinSdkAttributes")); } int?tryTargetSdkVersion = MonoAndroidHelper.SupportedVersions.GetApiLevelFromId(targetSdkVersion); if (!tryTargetSdkVersion.HasValue) { throw new InvalidOperationException(string.Format("The targetSdkVersion ({0}) is not a valid API level", targetSdkVersion)); } int targetSdkVersionValue = tryTargetSdkVersion.Value; foreach (var t in subclasses) { if (t.IsAbstract) { continue; } if (PackageName == null) { PackageName = t.Namespace; } var name = JavaNativeTypeManager.ToJniName(t).Replace('/', '.'); var compatName = JavaNativeTypeManager.ToCompatJniName(t).Replace('/', '.'); if (((string)app.Attribute(attName)) == compatName) { app.SetAttributeValue(attName, name); } Func <TypeDefinition, string, int, XElement> generator = GetGenerator(t); if (generator == null) { continue; } try { // activity not present: create a launcher for it IFF it has attribute if (!existingTypes.Contains(name) && !existingTypes.Contains(compatName)) { XElement fromCode = generator(t, name, targetSdkVersionValue); if (fromCode == null) { continue; } IEnumerable <MethodDefinition> constructors = t.Methods.Where(m => m.IsConstructor).Cast <MethodDefinition> (); if (!constructors.Any(c => !c.HasParameters && c.IsPublic)) { string message = $"The type '{t.FullName}' must provide a public default constructor"; SequencePoint sourceLocation = FindSource(constructors); if (sourceLocation != null && sourceLocation.Document?.Url != null) { log.LogError( subcategory: String.Empty, errorCode: "XA4213", helpKeyword: String.Empty, file: sourceLocation.Document.Url, lineNumber: sourceLocation.StartLine, columnNumber: sourceLocation.StartColumn, endLineNumber: sourceLocation.EndLine, endColumnNumber: sourceLocation.EndColumn, message: message); } else { log.LogCodedError("XA4213", message); } continue; } app.Add(fromCode); } foreach (var d in app.Descendants().Where(a => ((string)a.Attribute(attName)) == compatName)) { d.SetAttributeValue(attName, name); } } catch (InvalidActivityNameException ex) { log.LogErrorFromException(ex); } } var icon = app.Attribute(androidNs + "icon"); if (icon == null) { var activity = app.Element("activity"); if (activity != null) { var activityIcon = activity.Attribute(androidNs + "icon"); if (activityIcon != null) { app.Add(new XAttribute(androidNs + "icon", activityIcon.Value)); } } } PackageName = AndroidAppManifest.CanonicalizePackageName(PackageName); if (!PackageName.Contains('.')) { throw new InvalidOperationException("/manifest/@package attribute MUST contain a period ('.')."); } manifest.SetAttributeValue("package", PackageName); if (MultiDex) { app.Add(CreateMonoRuntimeProvider("mono.android.MultiDexLoader", null, initOrder: --AppInitOrder)); } var providerNames = AddMonoRuntimeProviders(app); if (Debug && !embed && InstantRunEnabled) { if (int.TryParse(SdkVersion, out int apiLevel) && apiLevel >= 19) { app.Add(CreateMonoRuntimeProvider("mono.android.ResourcePatcher", null, initOrder: --AppInitOrder)); } } if (Debug) { app.Add(new XComment("suppress ExportedReceiver")); app.Add(new XElement("receiver", new XAttribute(androidNs + "name", "mono.android.Seppuku"), new XElement("intent-filter", new XElement("action", new XAttribute(androidNs + "name", "mono.android.intent.action.SEPPUKU")), new XElement("category", new XAttribute(androidNs + "name", "mono.android.intent.category.SEPPUKU." + PackageName))))); if (app.Attribute(androidNs + "debuggable") == null) { app.Add(new XAttribute(androidNs + "debuggable", "true")); } } if (Debug || NeedsInternet) { AddInternetPermissionForDebugger(); } if (!embed) { AddFastDeployPermissions(); } // If the manifest has android:installLocation, but we are targeting // API 7 or lower, remove it for the user and show a warning if (manifest.Attribute(androidNs + "installLocation") != null) { if (targetSdkVersionValue < 8) { manifest.Attribute(androidNs + "installLocation").Remove(); Console.Error.WriteLine("monodroid: warning 1 : installLocation cannot be specified for Android versions less than 2.2. Attribute installLocation ignored."); } } AddInstrumentations(manifest, subclasses, targetSdkVersionValue); AddPermissions(app); AddPermissionGroups(app); AddPermissionTrees(app); AddUsesPermissions(app); AddUsesFeatures(app); AddSupportsGLTextures(app); ReorderActivityAliases(app); ReorderElements(app); if (mergedManifestDocuments != null) { foreach (var mergedManifest in mergedManifestDocuments) { try { MergeLibraryManifest(mergedManifest); } catch (Exception ex) { log.LogCodedWarning("XA4302", "Unhandled exception merging `AndroidManifest.xml`: {0}", ex); } } } return(providerNames); SequencePoint FindSource(IEnumerable <MethodDefinition> methods) { if (methods == null) { return(null); } SequencePoint ret = null; foreach (MethodDefinition method in methods.Where(m => m != null && m.HasBody && m.DebugInformation != null)) { foreach (Instruction ins in method.Body.Instructions) { SequencePoint seq = method.DebugInformation.GetSequencePoint(ins); if (seq == null) { continue; } if (ret == null || seq.StartLine < ret.StartLine) { ret = seq; } break; } } return(ret); } }