private void AddAdditionalNativeLibraries (ArchiveFileList files, string [] supportedAbis) { if (AdditionalNativeLibraryReferences == null || !AdditionalNativeLibraryReferences.Any ()) return; var libs = AdditionalNativeLibraryReferences .Select (l => new LibInfo { Path = l.ItemSpec, Abi = AndroidRidAbiHelper.GetNativeLibraryAbi (l) }); AddNativeLibraries (files, supportedAbis, libs); }
public override bool RunTask() { if (InputLibraries == null || InputLibraries.Length == 0) { return(true); } var output = new List <ITaskItem> (InputLibraries.Length); foreach (var library in InputLibraries) { var abi = AndroidRidAbiHelper.GetNativeLibraryAbi(library); if (string.IsNullOrEmpty(abi)) { var packageId = library.GetMetadata("NuGetPackageId"); if (!string.IsNullOrEmpty(packageId)) { Log.LogCodedWarning("XA4301", library.ItemSpec, 0, Properties.Resources.XA4301_ABI_NuGet, library.ItemSpec, packageId); } else { Log.LogCodedWarning("XA4301", library.ItemSpec, 0, Properties.Resources.XA4301_ABI, library.ItemSpec); } continue; } // Both libmono-android.debug.so and libmono-android.release.so are in InputLibraries. // Use IncludeDebugSymbols to determine which one to include. // We may eventually have files such as `libmono-android-checked+asan.release.so` as well. var fileName = Path.GetFileNameWithoutExtension(library.ItemSpec); if (fileName.StartsWith("libmono-android", StringComparison.Ordinal)) { if (fileName.EndsWith(".debug", StringComparison.Ordinal)) { if (!IncludeDebugSymbols) { continue; } library.SetMetadata("ArchiveFileName", "libmonodroid.so"); } else if (fileName.EndsWith(".release", StringComparison.Ordinal)) { if (IncludeDebugSymbols) { continue; } library.SetMetadata("ArchiveFileName", "libmonodroid.so"); } } output.Add(library); } OutputLibraries = output.ToArray(); return(!Log.HasLoggedErrors); }
string GetNativeLibraryAbi (ITaskItem lib) { // If Abi is explicitly specified, simply return it. var lib_abi = AndroidRidAbiHelper.GetNativeLibraryAbi (lib); if (string.IsNullOrWhiteSpace (lib_abi)) { Log.LogCodedError ("XA4301", lib.ItemSpec, 0, Properties.Resources.XA4301_ABI, lib.ItemSpec); return null; } return lib_abi; }
public override bool RunTask() { var outDirInfo = new DirectoryInfo(OutputDirectory); // Copy files into _NativeLibraryImportsDirectoryName (native_library_imports) dir. if (!outDirInfo.Exists) { outDirInfo.Create(); } foreach (var lib in EmbeddedNativeLibraries) { // seealso bug #3477 to find out why we use this method. var abi = AndroidRidAbiHelper.GetNativeLibraryAbi(lib); if (abi == null) { Log.LogWarning( subcategory: string.Empty, warningCode: "XA4300", helpKeyword: string.Empty, file: lib.ItemSpec, lineNumber: 0, columnNumber: 0, endLineNumber: 0, endColumnNumber: 0, message: Properties.Resources.XA4300, messageArgs: new [] { lib.ItemSpec, } ); continue; } if (!outDirInfo.GetDirectories(abi).Any()) { outDirInfo.CreateSubdirectory(abi); } Files.CopyIfChanged(lib.ItemSpec, Path.Combine(OutputDirectory, abi, Path.GetFileName(lib.ItemSpec))); } var outpath = Path.Combine(outDirInfo.Parent.FullName, "__AndroidNativeLibraries__.zip"); if (Files.ArchiveZip(outpath, f => { using (var zip = new ZipArchiveEx(f)) { zip.AddDirectory(OutputDirectory, "native_library_imports"); } })) { Log.LogDebugMessage("Saving contents to " + outpath); } return(!Log.HasLoggedErrors); }
public override bool RunTask() { if (SourceFiles.Length != DestinationFiles.Length) { throw new ArgumentException("source and destination count mismatch"); } if (SourceFiles == null || SourceFiles.Length == 0) { return(true); } for (int i = 0; i < SourceFiles.Length; i++) { source = SourceFiles [i]; destination = DestinationFiles [i]; var abi = AndroidRidAbiHelper.GetNativeLibraryAbi(source); if (string.IsNullOrEmpty(abi)) { var packageId = source.GetMetadata("NuGetPackageId"); if (!string.IsNullOrEmpty(packageId)) { Log.LogCodedWarning("XA4301", source.ItemSpec, 0, Properties.Resources.XA4301_ABI_NuGet, source.ItemSpec, packageId); } else { Log.LogCodedWarning("XA4301", source.ItemSpec, 0, Properties.Resources.XA4301_ABI, source.ItemSpec); } continue; } triple = GetNdkTripleFromAbi(abi); Directory.CreateDirectory(Path.GetDirectoryName(destination.ItemSpec)); // This runs the tool base.RunTask(); // Stop early on failure if (Log.HasLoggedErrors) { return(false); } } return(!Log.HasLoggedErrors); }
public override bool RunTask() { if (!Directory.Exists(TargetDirectory)) { Log.LogDebugMessage("Target directory was not found"); return(true); } var manifestDocuments = new List <ITaskItem> (); var nativeLibraries = new List <ITaskItem> (); var jarFiles = new List <ITaskItem> (); foreach (var file in Directory.EnumerateFiles(TargetDirectory, "*", SearchOption.AllDirectories)) { if (file.EndsWith(".so", StringComparison.OrdinalIgnoreCase)) { if (AndroidRidAbiHelper.GetNativeLibraryAbi(file) != null) { nativeLibraries.Add(new TaskItem(file)); } } else if (file.EndsWith(".jar", StringComparison.OrdinalIgnoreCase)) { jarFiles.Add(new TaskItem(file)); } else if (file.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)) { if (Path.GetFileName(file) == "AndroidManifest.xml") { // there could be ./AndroidManifest.xml and bin/AndroidManifest.xml, which will be the same. So, ignore "bin" ones. var directory = Path.GetFileName(Path.GetDirectoryName(file)); if (IgnoredManifestDirectories.Contains(directory)) { continue; } manifestDocuments.Add(new TaskItem(file)); } } } ManifestDocuments = manifestDocuments.ToArray(); NativeLibraries = nativeLibraries.ToArray(); Jars = jarFiles.ToArray(); if (!string.IsNullOrEmpty(CacheFile)) { var document = new XDocument( new XDeclaration("1.0", "UTF-8", null), new XElement("Paths", new XElement("ManifestDocuments", ManifestDocuments.Select(e => new XElement("ManifestDocument", e.ItemSpec))), new XElement("NativeLibraries", NativeLibraries.Select(e => new XElement("NativeLibrary", e.ItemSpec))), new XElement("Jars", Jars.Select(e => new XElement("Jar", e.ItemSpec))) )); document.SaveIfChanged(CacheFile); } Log.LogDebugTaskItems(" NativeLibraries: ", NativeLibraries); Log.LogDebugTaskItems(" Jars: ", Jars); Log.LogDebugTaskItems(" ManifestDocuments: ", ManifestDocuments); return(true); }
public override bool RunTask() { Directory.CreateDirectory(Path.GetDirectoryName(OutputFile)); using (var stream = File.Create(OutputFile)) using (var aar = ZipArchive.Open(stream)) { var existingEntries = new HashSet <string> (StringComparer.Ordinal); foreach (var entry in aar) { Log.LogDebugMessage("Existing entry: " + entry.FullName); existingEntries.Add(entry.FullName); } if (AndroidAssets != null) { foreach (var asset in AndroidAssets) { // See: https://github.com/xamarin/xamarin-android/commit/665cb59205f8ac565b6acbda740624844bc1cbd9 if (Directory.Exists(asset.ItemSpec)) { Log.LogDebugMessage($"Skipping item, is a directory: {asset.ItemSpec}"); continue; } var relative = MonoAndroidHelper.GetRelativePathForAndroidAsset(AssetDirectory, asset); var archivePath = "assets/" + relative.Replace('\\', '/'); aar.AddStream(File.OpenRead(asset.ItemSpec), archivePath); existingEntries.Remove(archivePath); } } if (AndroidResources != null) { var nameCaseMap = new StringBuilder(); foreach (var resource in AndroidResources) { // See: https://github.com/xamarin/xamarin-android/commit/665cb59205f8ac565b6acbda740624844bc1cbd9 if (Directory.Exists(resource.ItemSpec)) { Log.LogDebugMessage($"Skipping item, is a directory: {resource.ItemSpec}"); continue; } var directory = Path.GetDirectoryName(resource.ItemSpec); var resourcePath = Path.GetFileName(directory) + "/" + Path.GetFileName(resource.ItemSpec); var archivePath = "res/" + resourcePath; aar.AddStream(File.OpenRead(resource.ItemSpec), archivePath); existingEntries.Remove(archivePath); nameCaseMap.Append(resource.GetMetadata("LogicalName").Replace('\\', '/')); nameCaseMap.Append(';'); nameCaseMap.AppendLine(resourcePath); } if (nameCaseMap.Length > 0) { var archivePath = ".net/__res_name_case_map.txt"; aar.AddEntry(archivePath, nameCaseMap.ToString(), Files.UTF8withoutBOM); existingEntries.Remove(archivePath); } } if (AndroidEnvironment != null) { foreach (var env in AndroidEnvironment) { var archivePath = $".net/env/{GetHashedFileName (env)}.env"; aar.AddStream(File.OpenRead(env.ItemSpec), archivePath); existingEntries.Remove(archivePath); } } if (JarFiles != null) { foreach (var jar in JarFiles) { var archivePath = $"libs/{GetHashedFileName (jar)}.jar"; aar.AddStream(File.OpenRead(jar.ItemSpec), archivePath); existingEntries.Remove(archivePath); } } if (NativeLibraries != null) { foreach (var lib in NativeLibraries) { var abi = AndroidRidAbiHelper.GetNativeLibraryAbi(lib); if (string.IsNullOrWhiteSpace(abi)) { Log.LogCodedError("XA4301", lib.ItemSpec, 0, Properties.Resources.XA4301_ABI, lib.ItemSpec); continue; } var archivePath = "jni/" + abi + "/" + Path.GetFileName(lib.ItemSpec); aar.AddStream(File.OpenRead(lib.ItemSpec), archivePath); existingEntries.Remove(archivePath); } } foreach (var entry in existingEntries) { Log.LogDebugMessage($"Removing {entry} as it is not longer required."); aar.DeleteEntry(entry); } } // Delete the archive on failure if (Log.HasLoggedErrors && File.Exists(OutputFile)) { File.Delete(OutputFile); } return(!Log.HasLoggedErrors); }