IEnumerable <NativeReferenceMetadata> ReadManifest(string manifestPath) { XmlDocument document = new XmlDocument(); document.LoadWithoutNetworkAccess(manifestPath); foreach (XmlNode referenceNode in document.GetElementsByTagName("NativeReference")) { NativeReferenceMetadata metadata = new NativeReferenceMetadata(); metadata.LibraryName = Path.Combine(Path.GetDirectoryName(manifestPath), referenceNode.Attributes ["Name"].Value); var attributes = new Dictionary <string, string> (); foreach (XmlNode attribute in referenceNode.ChildNodes) { attributes [attribute.Name] = attribute.InnerText; } metadata.ForceLoad = ParseAttributeWithDefault(attributes ["ForceLoad"], false); metadata.Frameworks = attributes ["Frameworks"]; metadata.WeakFrameworks = attributes ["WeakFrameworks"]; metadata.LinkerFlags = attributes ["LinkerFlags"]; metadata.NeedsGccExceptionHandling = ParseAttributeWithDefault(attributes ["NeedsGccExceptionHandling"], false); metadata.IsCxx = ParseAttributeWithDefault(attributes ["IsCxx"], false); metadata.SmartLink = ParseAttributeWithDefault(attributes ["SmartLink"], true); // TODO - The project attributes do not contain these bits, is that OK? //metadata.LinkTarget = (LinkTarget) Enum.Parse (typeof (LinkTarget), attributes ["LinkTarget"]); //metadata.Dlsym = (DlsymOption)Enum.Parse (typeof (DlsymOption), attributes ["Dlsym"]); yield return(metadata); } }
string ExtractNativeLibrary(AssemblyDefinition assembly, NativeReferenceMetadata metadata) { string path = Path.Combine(App.Cache.Location, metadata.LibraryName); if (!Application.IsUptodate(FullPath, path)) { Application.ExtractResource(assembly.MainModule, metadata.LibraryName, path, false); Driver.Log(3, "Extracted third-party binding '{0}' from '{1}' to '{2}'", metadata.LibraryName, FullPath, path); LogNativeReference(metadata); } else { Driver.Log(3, "Target '{0}' is up-to-date.", path); } if (!File.Exists(path)) { ErrorHelper.Warning(1302, "Could not extract the native library '{0}' from '{1}'. " + "Please ensure the native library was properly embedded in the managed assembly " + "(if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').", metadata.LibraryName, path); } return(path); }
static void LogNativeReference(NativeReferenceMetadata metadata) { Driver.Log(3, " LibraryName: {0}", metadata.LibraryName); Driver.Log(3, " From: {0}", metadata.Attribute != null ? "LinkWith" : "Binding Manifest"); Driver.Log(3, " ForceLoad: {0}", metadata.ForceLoad); Driver.Log(3, " Frameworks: {0}", metadata.Frameworks); Driver.Log(3, " IsCxx: {0}", metadata.IsCxx); Driver.Log(3, " LinkerFlags: {0}", metadata.LinkerFlags); Driver.Log(3, " LinkTarget: {0}", metadata.LinkTarget); Driver.Log(3, " NeedsGccExceptionHandling: {0}", metadata.NeedsGccExceptionHandling); Driver.Log(3, " SmartLink: {0}", metadata.SmartLink); Driver.Log(3, " WeakFrameworks: {0}", metadata.WeakFrameworks); }
void ProcessNativeReferenceOptions(NativeReferenceMetadata metadata) { // We can't add -dead_strip if there are any LinkWith attributes where smart linking is disabled. if (!metadata.SmartLink) { App.DeadStrip = false; } // Don't add -force_load if the binding's SmartLink value is set and the static registrar is being used. if (metadata.ForceLoad && !(metadata.SmartLink && App.Registrar == RegistrarMode.Static)) { ForceLoad = true; } if (!string.IsNullOrEmpty(metadata.LinkerFlags)) { if (LinkerFlags == null) { LinkerFlags = new List <string> (); } if (!StringUtils.TryParseArguments(metadata.LinkerFlags, out string [] args, out var ex))
string ExtractFramework(AssemblyDefinition assembly, NativeReferenceMetadata metadata) { string path = Path.Combine(App.Cache.Location, metadata.LibraryName); var zipPath = path + ".zip"; if (!Application.IsUptodate(FullPath, zipPath)) { Application.ExtractResource(assembly.MainModule, metadata.LibraryName, zipPath, false); Driver.Log(3, "Extracted third-party framework '{0}' from '{1}' to '{2}'", metadata.LibraryName, FullPath, zipPath); LogNativeReference(metadata); } else { Driver.Log(3, "Target '{0}' is up-to-date.", path); } if (!File.Exists(zipPath)) { ErrorHelper.Warning(1302, "Could not extract the native framework '{0}' from '{1}'. " + "Please ensure the native framework was properly embedded in the managed assembly " + "(if the assembly was built using a binding project, the native framework must be included in the project, and its Build Action must be 'ObjcBindingNativeFramework').", metadata.LibraryName, zipPath); } else { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } if (Driver.RunCommand("/usr/bin/unzip", string.Format("-u -o -d {0} {1}", StringUtils.Quote(path), StringUtils.Quote(zipPath))) != 0) { throw ErrorHelper.CreateError(1303, "Could not decompress the native framework '{0}' from '{1}'. Please review the build log for more information from the native 'unzip' command.", metadata.LibraryName, zipPath); } } return(path); }
void ProcessLinkWithAttributes(AssemblyDefinition assembly) { // // Tasks: // * Remove LinkWith attribute: this is done in the linker. // * Remove embedded resources related to LinkWith attribute from assembly: this is done at a later stage, // here we just compile a list of resources to remove. // * Extract embedded resources related to LinkWith attribute to a file // * Modify the linker flags used to build/link the dylib (if fastdev) or the main binary (if !fastdev) // for (int i = 0; i < assembly.CustomAttributes.Count; i++) { CustomAttribute attr = assembly.CustomAttributes [i]; if (attr.Constructor == null) { continue; } TypeReference type = attr.Constructor.DeclaringType; if (!type.IsPlatformType("ObjCRuntime", "LinkWithAttribute")) { continue; } // Let the linker remove it the attribute from the assembly HasLinkWithAttributes = true; LinkWithAttribute linkWith = GetLinkWithAttribute(attr); NativeReferenceMetadata metadata = new NativeReferenceMetadata(linkWith); // If we've already processed this native library, skip it if (LinkWith.Any(x => Path.GetFileName(x) == metadata.LibraryName) || Frameworks.Any(x => Path.GetFileName(x) == metadata.LibraryName)) { continue; } // Remove the resource from the assembly at a later stage. if (!string.IsNullOrEmpty(metadata.LibraryName)) { AddResourceToBeRemoved(metadata.LibraryName); } ProcessNativeReferenceOptions(metadata); if (!string.IsNullOrEmpty(linkWith.LibraryName)) { if (linkWith.LibraryName.EndsWith(".framework", StringComparison.OrdinalIgnoreCase)) { AssertiOSVersionSupportsUserFrameworks(linkWith.LibraryName); Frameworks.Add(ExtractFramework(assembly, metadata)); } else { LinkWith.Add(ExtractNativeLibrary(assembly, metadata)); } } } }
void ProcessLinkWithAttributes(AssemblyDefinition assembly) { // // Tasks: // * Remove LinkWith attribute: this is done in the linker. // * Remove embedded resources related to LinkWith attribute from assembly: this is done at a later stage, // here we just compile a list of resources to remove. // * Extract embedded resources related to LinkWith attribute to a file // * Modify the linker flags used to build/link the dylib (if fastdev) or the main binary (if !fastdev) // for (int i = 0; i < assembly.CustomAttributes.Count; i++) { CustomAttribute attr = assembly.CustomAttributes [i]; if (attr.Constructor == null) { continue; } TypeReference type = attr.Constructor.DeclaringType; if (!type.Is("ObjCRuntime", "LinkWithAttribute")) { continue; } // Let the linker remove it the attribute from the assembly HasLinkWithAttributes = true; LinkWithAttribute linkWith = GetLinkWithAttribute(attr); NativeReferenceMetadata metadata = new NativeReferenceMetadata(linkWith); // If we've already processed this native library, skip it if (LinkWith.Any(x => Path.GetFileName(x) == metadata.LibraryName) || Frameworks.Any(x => Path.GetFileName(x) == metadata.LibraryName)) { continue; } // Remove the resource from the assembly at a later stage. if (!string.IsNullOrEmpty(metadata.LibraryName)) { AddResourceToBeRemoved(metadata.LibraryName); } ProcessNativeReferenceOptions(metadata); if (!string.IsNullOrEmpty(linkWith.LibraryName)) { switch (Path.GetExtension(linkWith.LibraryName).ToLowerInvariant()) { case ".framework": AssertiOSVersionSupportsUserFrameworks(linkWith.LibraryName); Frameworks.Add(ExtractFramework(assembly, metadata)); break; case ".xcframework": // this is resolved, at msbuild time, into a framework // but we must ignore it here (can't be the `default` case) break; default: LinkWith.Add(ExtractNativeLibrary(assembly, metadata)); break; } } } }
void ProcessNativeReferenceOptions(NativeReferenceMetadata metadata) { // We can't add -dead_strip if there are any LinkWith attributes where smart linking is disabled. if (!metadata.SmartLink) { App.DeadStrip = false; } // Don't add -force_load if the binding's SmartLink value is set and the static registrar is being used. if (metadata.ForceLoad && !(metadata.SmartLink && App.Registrar == RegistrarMode.Static)) { ForceLoad = true; } if (!string.IsNullOrEmpty(metadata.LinkerFlags)) { if (LinkerFlags == null) { LinkerFlags = new List <string> (); } LinkerFlags.Add(metadata.LinkerFlags); } if (!string.IsNullOrEmpty(metadata.Frameworks)) { foreach (var f in metadata.Frameworks.Split(new char [] { ' ' })) { if (Frameworks == null) { Frameworks = new HashSet <string> (); } Frameworks.Add(f); } } if (!string.IsNullOrEmpty(metadata.WeakFrameworks)) { foreach (var f in metadata.WeakFrameworks.Split(new char [] { ' ' })) { if (WeakFrameworks == null) { WeakFrameworks = new HashSet <string> (); } WeakFrameworks.Add(f); } } if (metadata.NeedsGccExceptionHandling) { NeedsGccExceptionHandling = true; } if (metadata.IsCxx) { EnableCxx = true; } #if MONOTOUCH if (metadata.Dlsym != DlsymOption.Default) { App.SetDlsymOption(FullPath, metadata.Dlsym == DlsymOption.Required); } #endif }