Пример #1
0
        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(' ');
                }
            }
        }
Пример #2
0
        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")));
            }
        }
Пример #3
0
        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")));
            }
        }
Пример #4
0
        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));
            }
        }
Пример #5
0
        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));
            }
        }
Пример #6
0
        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));
        }
Пример #7
0
        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));
            }
        }
Пример #8
0
        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);
                }
            }
        }