void AppendLibraryAndFrameworks(StringBuilder sb, IEnumerable <string> candidateDirectories, string [] modNames, bool addReference) { List <string> candidates = candidateDirectories.ToList(); List <string> fwkDirectories = new List <string> (); List <string> libs = new List <string> (); List <string> fwks = new List <string> (); foreach (string moduleName in modNames) { string swiftModule = moduleName + ".swiftmodule"; bool addedFwk = false; for (int i = 0; i < candidates.Count(); i++) { // if it's a framework, there will be a one-to-one mapping of module names -> framework directories // remove the path from the candidate and move it to fwkDirectories // and add the name to fwks if (SwiftModuleFinder.IsAppleFramework(candidates [i], swiftModule)) { fwks.Add(moduleName); fwkDirectories.Add(candidates [i]); candidates.RemoveAt(i); addedFwk = true; break; } } // if we didn't add a framework, it's probably a library if (!addedFwk) { libs.Add(moduleName); } addedFwk = false; } foreach (string libdir in candidates) { sb.Append("-L ").Append(QuoteIfNeeded(libdir)).Append(' '); } foreach (string fwkdir in fwkDirectories) { string parentdir = ReliablePath.GetParentDirectory(fwkdir); sb.Append("-F ").Append(QuoteIfNeeded(parentdir)).Append(' '); } sb.Append("-L ").Append(QuoteIfNeeded(CompilerInfo.LibDirectory)).Append(' '); if (addReference) { foreach (string lib in libs) { sb.Append("-l").Append(lib).Append(' '); } foreach (string fwk in fwks) { sb.Append("-framework ").Append(fwk).Append(' '); } } }
public void GetDirectLayoutModuleName() { using (var tmp = new DisposableTempDirectory()) { CreateFileAtLocation(tmp.DirectoryPath, "Foo"); Assert.IsNull(SwiftModuleFinder.GetDirectLayoutModuleName(Path.Combine(tmp.DirectoryPath, "Foo"))); CreateFileAtLocation(tmp.DirectoryPath, "Bar.swiftmodule"); Assert.AreEqual("Bar", SwiftModuleFinder.GetDirectLayoutModuleName(Path.Combine(tmp.DirectoryPath, "Bar.swiftmodule"))); } }
public void GetAppleModuleName_RequiresValidName() { using (var tmp = new DisposableTempDirectory()) { CreateFileAtLocation(tmp.DirectoryPath, "Foo", "Modules", "Foo.swiftmodule"); Assert.IsNull(SwiftModuleFinder.GetAppleModuleName(Path.Combine(tmp.DirectoryPath, "Foo"))); CreateFileAtLocation(tmp.DirectoryPath, ".framework", "Modules", ".swiftmodule"); Assert.IsNull(SwiftModuleFinder.GetAppleModuleName(Path.Combine(tmp.DirectoryPath, ".framework"))); } }
public void GetAppleModuleName_OnlyWorksWithValidStructure() { using (var tmp = new DisposableTempDirectory()) { string framework = Path.Combine(tmp.DirectoryPath, "Foo.framework"); Directory.CreateDirectory(Path.Combine(framework, "Modules")); Assert.IsNull(SwiftModuleFinder.GetAppleModuleName(framework)); File.Create(Path.Combine(framework, "Modules", "Foo.swiftmodule")); Assert.AreEqual("Foo", SwiftModuleFinder.GetAppleModuleName(framework)); } }
public void GetXamarinModuleName_OnlyWorksWithValidStructure() { const string Arch = "x86_64"; using (var tmp = new DisposableTempDirectory()) { string folder = Path.Combine(tmp.DirectoryPath, "Foo"); Directory.CreateDirectory(Path.Combine(folder, Arch)); Assert.IsNull(SwiftModuleFinder.GetXamarinModuleName(folder, Arch)); CreateFileAtLocation(folder, "x86_64", "Foo.swiftmodule"); Assert.AreEqual("Foo", SwiftModuleFinder.GetXamarinModuleName(folder, Arch)); } }
public List <ModuleDeclaration> ReflectToModules(IEnumerable <string> includeDirectories, IEnumerable <string> libraryDirectories, string extraArgs, params string [] moduleNames) { var moduleNameAggregate = moduleNames.Aggregate((s1, s2) => s1 + s2); var pathName = tempDirectory.UniquePath(moduleNameAggregate, null, "xml"); includeDirectories = includeDirectories ?? new string [] { tempDirectory.DirectoryPath }; libraryDirectories = libraryDirectories ?? new string [] { tempDirectory.DirectoryPath }; var modulesInLibraries = SwiftModuleFinder.FindModuleNames(libraryDirectories, CompilerInfo.Target); List <ISwiftModuleLocation> locations = SwiftModuleFinder.GatherAllReferencedModules(modulesInLibraries, includeDirectories, CompilerInfo.Target); string output = ""; try { output = Reflect(locations.Select(loc => loc.DirectoryPath), libraryDirectories, pathName, extraArgs, moduleNames); } finally { locations.DisposeAll(); } ThrowOnCompilerVersionMismatch(output, moduleNames); return(Reflector.FromXmlFile(pathName)); }
public Tuple <string, HashSet <string> > CompileWrappers(string [] inputLibraryDirectories, string [] inputModuleDirectories, IEnumerable <ModuleDeclaration> modulesToCompile, ModuleInventory modInventory, List <string> targets, string wrappingModuleName, bool outputIsFramework) { wrappingModuleName = wrappingModuleName ?? kXamWrapPrefix; string outputLibraryName = BuildLibraryName(wrappingModuleName, outputIsFramework); string outputLibraryPath = Path.Combine(outputDirectory, outputLibraryName); string outputFrameworkPath = Path.Combine(outputDirectory, Path.GetFileName(outputLibraryName) + ".framework"); string outputFrameworkLibPath = Path.Combine(outputFrameworkPath, outputLibraryName); if (File.Exists(outputLibraryPath)) { File.Delete(outputLibraryPath); } using (TempDirectorySwiftClassFileProvider fileProvider = new TempDirectorySwiftClassFileProvider(Ex.ThrowOnNull(wrappingModuleName, "wrappingModuleName"), true)) { var allReferencedModules = new HashSet <string> (); foreach (ModuleDeclaration module in modulesToCompile) { HashSet <string> referencedModules = null; var wrappedClasses = Wrap(module, modInventory, fileProvider, typeMapper, wrappingModuleName, out referencedModules, errors); this.wrappers.Add(module.Name, wrappedClasses); allReferencedModules.Merge(referencedModules); } var inModuleNamesList = modulesToCompile.Select(mod => mod.Name).ToList(); inModuleNamesList.Add("XamGlue"); if (fileProvider.IsEmpty) { return(new Tuple <string, HashSet <string> > (null, null)); } var targetOutDirs = new List <string> (); for (int i = 0; i < targets.Count; i++) { // each file goes to a unique output directory. // first compile into the fileProvider, then move to // fileProvider/tar-get-arch string targetoutdir = Path.Combine(fileProvider.DirectoryPath, targets [i]); targetOutDirs.Add(targetoutdir); Directory.CreateDirectory(targetoutdir); var locations = SwiftModuleFinder.GatherAllReferencedModules(allReferencedModules, inputModuleDirectories, targets [i]); try { string [] inputModDirs = locations.Select(loc => loc.DirectoryPath).ToArray(); CompileAllFiles(fileProvider, wrappingModuleName, outputLibraryName, outputLibraryPath, inputModDirs, inputLibraryDirectories, inModuleNamesList.ToArray(), targets [i], outputIsFramework); } catch (Exception e) { throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 66, e, $"Failed to compile the generated swift wrapper code."); } finally { locations.DisposeAll(); } // move to arch directory File.Copy(Path.Combine(fileProvider.DirectoryPath, outputLibraryName), Path.Combine(targetoutdir, outputLibraryName), true); File.Delete(Path.Combine(fileProvider.DirectoryPath, outputLibraryName)); File.Copy(Path.Combine(fileProvider.DirectoryPath, wrappingModuleName + ".swiftmodule"), Path.Combine(targetoutdir, wrappingModuleName + ".swiftmodule")); File.Delete(Path.Combine(fileProvider.DirectoryPath, wrappingModuleName + ".swiftmodule")); File.Copy(Path.Combine(fileProvider.DirectoryPath, wrappingModuleName + ".swiftdoc"), Path.Combine(targetoutdir, wrappingModuleName + ".swiftdoc")); File.Delete(Path.Combine(fileProvider.DirectoryPath, wrappingModuleName + ".swiftdoc")); } if (targets.Count > 1) { // lipo all the outputs back into the fileProvider Lipo(targetOutDirs, fileProvider.DirectoryPath, outputLibraryName); File.Copy(Path.Combine(fileProvider.DirectoryPath, outputLibraryName), outputLibraryPath, true); if (!IsMacOSLib(outputLibraryPath)) { if (!Directory.Exists(outputFrameworkPath)) { Directory.CreateDirectory(outputFrameworkPath); } File.Copy(outputLibraryPath, outputFrameworkLibPath, true); InfoPList.MakeInfoPList(outputFrameworkLibPath, Path.Combine(outputFrameworkPath, "Info.plist")); } } else { File.Copy(Path.Combine(targetOutDirs [0], outputLibraryName), outputLibraryPath, true); if (!IsMacOSLib(outputLibraryPath)) { if (!Directory.Exists(outputFrameworkPath)) { Directory.CreateDirectory(outputFrameworkPath); } File.Copy(outputLibraryPath, outputFrameworkLibPath, true); InfoPList.MakeInfoPList(outputFrameworkLibPath, Path.Combine(outputFrameworkPath, "Info.plist")); } } for (int i = 0; i < targets.Count; i++) { string arch = targets [i].ClangTargetCpu(); string targetDir = Path.Combine(outputDirectory, arch); Directory.CreateDirectory(targetDir); File.Copy(Path.Combine(targetOutDirs [i], wrappingModuleName + ".swiftmodule"), Path.Combine(targetDir, wrappingModuleName + ".swiftmodule"), true); File.Copy(Path.Combine(targetOutDirs [i], wrappingModuleName + ".swiftdoc"), Path.Combine(targetDir, wrappingModuleName + ".swiftdoc"), true); } foreach (string dirname in targetOutDirs) { Directory.Delete(dirname, true); } if (retainSwiftFiles) { CopySwiftFiles(fileProvider, Path.Combine(outputDirectory, wrappingModuleName + "Source")); } return(new Tuple <string, HashSet <string> > (outputLibraryPath, allReferencedModules)); } }
public void CheckForOptionErrors(ErrorHandling errors) { CheckPath(SwiftBinPath, "path to swift binaries", errors); CheckPath(SwiftLibPath, "path to swift libraries", errors); TypeDatabasePaths.ForEach(path => CheckPath(path, "path to type database files", errors)); EnsureFileExists("swiftc", new string [] { SwiftBinPath }, errors); EnsureFileExists("swift", new string [] { SwiftBinPath }, errors); ModulePaths.ForEach(path => CheckPath(path, "module path", errors)); DylibPaths.ForEach(path => CheckPath(path, "library path", errors)); if (ModuleName != null) { string wholeModule = "lib" + ModuleName + ".dylib"; string libDir = DylibPaths.FirstOrDefault(path => File.Exists(Path.Combine(path, wholeModule))); if (libDir == null) { wholeModule = ModuleName; libDir = DylibPaths.FirstOrDefault(path => File.Exists(Path.Combine(path, wholeModule))); } if (libDir == null) { errors.Add(new ReflectorError(new FileNotFoundException($"Couldn't find module {ModuleName}"))); return; } string libFile = Path.Combine(libDir, wholeModule); using (FileStream stm = new FileStream(libFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { try { List <string> targets = MachOHelpers.TargetsFromDylib(stm); Targets = FilterTargetsIfNeeded(targets, libFile); if (Targets.Count > 0) { var targetOS = targets [0].ClangTargetOS(); if (SwiftGluePath != null) { string path = null; if (targetOS.StartsWith("macos", StringComparison.Ordinal)) { path = Path.Combine(SwiftGluePath, "mac/XamGlue.framework"); } else if (targetOS.StartsWith("ios", StringComparison.Ordinal)) { path = Path.Combine(SwiftGluePath, "iphone/XamGlue.framework"); } else if (targetOS.StartsWith("tvos", StringComparison.Ordinal)) { path = Path.Combine(SwiftGluePath, "appletv/XamGlue.framework"); } else if (targetOS.StartsWith("watchos", StringComparison.Ordinal)) { path = Path.Combine(SwiftGluePath, "watch/XamGlue.framework"); } if (path != null) { ModulePaths.Add(path); DylibPaths.Add(path); } } if (targetOS.StartsWith("macos", StringComparison.Ordinal)) { SwiftLibPath = Path.Combine(SwiftLibPath, "macosx"); } else if (targetOS.StartsWith("ios", StringComparison.Ordinal)) { SwiftLibPath = Path.Combine(SwiftLibPath, "iphoneos"); } else if (targetOS.StartsWith("tvos", StringComparison.Ordinal)) { SwiftLibPath = Path.Combine(SwiftLibPath, "appletvos"); } else if (targetOS.StartsWith("watchos", StringComparison.Ordinal)) { SwiftLibPath = Path.Combine(SwiftLibPath, "watchos"); } } // filter the targets here foreach (string target in Targets) { StringBuilder sb = new StringBuilder(); foreach (string s in ModulePaths.Interleave(", ")) { sb.Append(s); } using (ISwiftModuleLocation loc = SwiftModuleFinder.Find(ModulePaths, ModuleName, target)) { if (loc == null) { errors.Add(new ReflectorError(new FileNotFoundException($"Unable to find swift module file for {ModuleName} in target {target}. Searched in {sb.ToString ()}."))); } } using (ISwiftModuleLocation loc = SwiftModuleFinder.Find(ModulePaths, "XamGlue", target)) { if (loc == null) { errors.Add(new ReflectorError(new FileNotFoundException($"Unable to find swift module file for XamGlue in target {target}. Did you forget to refer to it with -M or -C? Searched in {sb.ToString ()}."))); } } } } catch (Exception err) { errors.Add(new RuntimeException(ReflectorError.kCantHappenBase + 63, true, err, $"{libFile}: {err.Message}")); } } } if (String.IsNullOrEmpty(OutputDirectory)) { ArgumentException ex = new ArgumentException("need to specify an output directory with -o"); errors.Add(ex); } else { if (File.Exists(OutputDirectory) && !File.GetAttributes(OutputDirectory).HasFlag(FileAttributes.Directory)) { errors.Add(new ReflectorError(new ArgumentException($"output directory {OutputDirectory} is a file. It needs to be a directory."))); return; } if (!Directory.Exists(OutputDirectory)) { Directory.CreateDirectory(OutputDirectory); } } }