예제 #1
0
        static int Main()
        {
            var paths = new XABuildPaths();

            if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
            {
                Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                return(1);
            }

            //Create a custom xabuild.exe.config
            CreateConfig(paths);

            //Create link to .NETFramework and .NETPortable directory
            foreach (var dir in Directory.GetDirectories(paths.SystemProfiles))
            {
                var name = Path.GetFileName(dir);
                if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir))
                {
                    return(1);
                }
            }

            return(MSBuildApp.Main());
        }
예제 #2
0
        static void CreateConfig(XABuildPaths paths)
        {
            var xml = new XmlDocument {
                XmlResolver = null
            };

            using (var reader = XmlReader.Create(paths.MSBuildConfig, new XmlReaderSettings {
                XmlResolver = null
            }))
                xml.Load(reader);

            var toolsets = xml.SelectSingleNode("configuration/msbuildToolsets/toolset");

            SetProperty(toolsets, "XABuild", "true");              // Enables MSBuild .targets to check for xabuild
            SetProperty(toolsets, "VsInstallRoot", paths.VsInstallRoot);
            SetProperty(toolsets, "MSBuildToolsPath", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath32", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath64", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildExtensionsPath", paths.MSBuildExtensionsPath);
            SetProperty(toolsets, "MSBuildExtensionsPath32", paths.MSBuildExtensionsPath);
            if (!string.IsNullOrEmpty(paths.RoslynTargetsPath))
            {
                SetProperty(toolsets, "RoslynTargetsPath", paths.RoslynTargetsPath);
            }
            SetProperty(toolsets, "NuGetProps", paths.NuGetProps);
            SetProperty(toolsets, "NuGetTargets", paths.NuGetTargets);
            SetProperty(toolsets, "NuGetRestoreTargets", paths.NuGetRestoreTargets);
            SetProperty(toolsets, "MonoAndroidToolsDirectory", paths.MonoAndroidToolsDirectory);
            SetProperty(toolsets, "TargetFrameworkRootPath", paths.FrameworksDirectory + Path.DirectorySeparatorChar);              //NOTE: Must include trailing \
            if (!string.IsNullOrEmpty(paths.AndroidSdkDirectory))
            {
                SetProperty(toolsets, "AndroidSdkDirectory", paths.AndroidSdkDirectory);
            }
            if (!string.IsNullOrEmpty(paths.AndroidNdkDirectory))
            {
                SetProperty(toolsets, "AndroidNdkDirectory", paths.AndroidNdkDirectory);
            }

            var projectImportSearchPaths = toolsets.SelectSingleNode("projectImportSearchPaths");
            var searchPaths = projectImportSearchPaths.SelectSingleNode($"searchPaths[@os='{paths.SearchPathsOS}']") as XmlElement;

            if (searchPaths != null)
            {
                foreach (XmlNode property in searchPaths.SelectNodes("property[starts-with(@name, 'MSBuildExtensionsPath')]/@value"))
                {
                    property.Value = "";
                }
            }

            Directory.CreateDirectory(paths.MSBuildTempPath);
            File.WriteAllText(paths.MSBuildExeTempPath, "");              // File just has to *exist*
            xml.Save(paths.XABuildConfig);

            if (Directory.Exists(paths.MSBuildSdksPath))
            {
                Environment.SetEnvironmentVariable("MSBuildSDKsPath", paths.MSBuildSdksPath, EnvironmentVariableTarget.Process);
            }
            Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", paths.MSBuildExeTempPath, EnvironmentVariableTarget.Process);
        }
예제 #3
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                var xml = CreateConfig(paths);

                //Symbolic links to be created: key=system, value=in-tree
                var symbolicLinks = new Dictionary <string, string> ();
                foreach (var dir in Directory.EnumerateDirectories(paths.SystemFrameworks))
                {
                    if (Path.GetFileName(dir) != "MonoAndroid")
                    {
                        symbolicLinks [dir] = Path.Combine(paths.FrameworksDirectory, Path.GetFileName(dir));
                    }
                }
                foreach (var dir in paths.SystemTargetsDirectories)
                {
                    symbolicLinks [dir] = Path.Combine(paths.MSBuildExtensionsPath, Path.GetFileName(dir));
                }
                if (symbolicLinks.Values.Any(d => !Directory.Exists(d)))
                {
                    //Hold open the file while creating the symbolic links
                    using (var writer = OpenSysLinksFile(paths)) {
                        foreach (var pair in symbolicLinks)
                        {
                            var systemDirectory = pair.Key;
                            var symbolicLink    = pair.Value;
                            Console.WriteLine($"[xabuild] creating symbolic link '{symbolicLink}' -> '{systemDirectory}'");
                            if (!SymbolicLink.Create(symbolicLink, systemDirectory))
                            {
                                return(1);
                            }
                            writer.WriteLine(Path.GetFileName(symbolicLink));
                        }
                    }
                }

                return(MSBuildApp.Main());
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
예제 #4
0
        static void CreateConfig(XABuildPaths paths)
        {
            var xml = new XmlDocument();

            xml.Load(paths.MSBuildConfig);

            var toolsets = xml.SelectSingleNode("configuration/msbuildToolsets/toolset");

            SetProperty(toolsets, "VsInstallRoot", paths.VsInstallRoot);
            SetProperty(toolsets, "MSBuildToolsPath", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath32", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath64", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildExtensionsPath", paths.MSBuildExtensionsPath);
            SetProperty(toolsets, "MSBuildExtensionsPath32", paths.MSBuildExtensionsPath);
            SetProperty(toolsets, "RoslynTargetsPath", Path.Combine(paths.MSBuildBin, "Roslyn"));
            SetProperty(toolsets, "AndroidSdkDirectory", paths.AndroidSdkDirectory);
            SetProperty(toolsets, "AndroidNdkDirectory", paths.AndroidNdkDirectory);
            SetProperty(toolsets, "MonoAndroidToolsDirectory", paths.MonoAndroidToolsDirectory);
            SetProperty(toolsets, "TargetFrameworkRootPath", paths.FrameworksDirectory + Path.DirectorySeparatorChar);              //NOTE: Must include trailing \

            var projectImportSearchPaths = toolsets.SelectSingleNode("projectImportSearchPaths");
            var searchPaths = projectImportSearchPaths.SelectSingleNode($"searchPaths[@os='{paths.SearchPathsOS}']") as XmlElement;

            //NOTE: on Linux, the searchPaths XML element does not exist, so we have to create it
            if (searchPaths == null)
            {
                searchPaths = xml.CreateElement("searchPaths");
                searchPaths.SetAttribute("os", paths.SearchPathsOS);

                var property = xml.CreateElement("property");
                property.SetAttribute("name", "MSBuildExtensionsPath");
                property.SetAttribute("value", "");
                searchPaths.AppendChild(property);

                property = xml.CreateElement("property");
                property.SetAttribute("name", "MSBuildExtensionsPath32");
                property.SetAttribute("value", "");
                searchPaths.AppendChild(property);

                property = xml.CreateElement("property");
                property.SetAttribute("name", "MSBuildExtensionsPath64");
                property.SetAttribute("value", "");
                searchPaths.AppendChild(property);

                projectImportSearchPaths.AppendChild(searchPaths);
            }

            foreach (XmlNode property in searchPaths.SelectNodes("property[starts-with(@name, 'MSBuildExtensionsPath')]/@value"))
            {
                property.Value = string.Join(";", paths.ProjectImportSearchPaths);
            }

            xml.Save(paths.XABuildConfig);

            Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", paths.MSBuildExeTempPath, EnvironmentVariableTarget.Process);
        }
예제 #5
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                var xml = CreateConfig(paths);

                //Hold open the file while creating the symbolic links
                using (var writer = OpenSysLinksFile(paths)) {
                    //Create link to .NETFramework and .NETPortable directory
                    foreach (var dir in Directory.GetDirectories(paths.SystemProfiles))
                    {
                        var name = Path.GetFileName(dir);
                        if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir))
                        {
                            return(1);
                        }
                        writer.WriteLine(name);
                    }
                }

                int exitCode = MSBuildApp.Main();
                if (exitCode != 0)
                {
                    Console.WriteLine($"MSBuildApp.Main exited with {exitCode}, xabuild configuration is:");

                    var settings = new XmlWriterSettings {
                        Indent = true,
                        NewLineOnAttributes = true,
                    };
                    using (var writer = XmlTextWriter.Create(Console.Out, settings)) {
                        xml.WriteTo(writer);
                    }
                }
                return(exitCode);
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
예제 #6
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                var xml = CreateConfig(paths);

                //Symbolic links to .NETFramework and .NETPortable directory
                var systemDirectories = Directory.EnumerateDirectories(paths.SystemProfiles)
                                        .Where(d => Path.GetFileName(d) != "MonoAndroid")   //NOTE: this happened on one of our VSTS build agents
                                        .ToArray();
                var symbolicLinks = systemDirectories
                                    .Select(d => Path.Combine(paths.FrameworksDirectory, Path.GetFileName(d)))
                                    .ToArray();

                if (symbolicLinks.Any(d => !Directory.Exists(d)))
                {
                    //Hold open the file while creating the symbolic links
                    using (var writer = OpenSysLinksFile(paths)) {
                        for (int i = 0; i < systemDirectories.Length; i++)
                        {
                            var symbolicLink    = symbolicLinks [i];
                            var systemDirectory = systemDirectories [i];
                            Console.WriteLine($"[xabuild] creating symbolic link '{symbolicLink}' -> '{systemDirectory}'");
                            if (!SymbolicLink.Create(symbolicLink, systemDirectory))
                            {
                                return(1);
                            }
                            writer.WriteLine(Path.GetFileName(symbolicLink));
                        }
                    }
                }

                return(MSBuildApp.Main());
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
예제 #7
0
        static XmlDocument CreateConfig(XABuildPaths paths)
        {
            var xml = new XmlDocument();

            xml.Load(paths.MSBuildConfig);

            var toolsets = xml.SelectSingleNode("configuration/msbuildToolsets/toolset");

            SetProperty(toolsets, "VsInstallRoot", paths.VsInstallRoot);
            SetProperty(toolsets, "MSBuildToolsPath", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath32", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildToolsPath64", paths.MSBuildBin);
            SetProperty(toolsets, "MSBuildExtensionsPath", paths.MSBuildExtensionsPath);
            SetProperty(toolsets, "MSBuildExtensionsPath32", paths.MSBuildExtensionsPath);
            if (!string.IsNullOrEmpty(paths.RoslynTargetsPath))
            {
                SetProperty(toolsets, "RoslynTargetsPath", paths.RoslynTargetsPath);
            }
            SetProperty(toolsets, "NuGetProps", paths.NuGetProps);
            SetProperty(toolsets, "NuGetTargets", paths.NuGetTargets);
            SetProperty(toolsets, "NuGetRestoreTargets", paths.NuGetRestoreTargets);
            SetProperty(toolsets, "MonoAndroidToolsDirectory", paths.MonoAndroidToolsDirectory);
            SetProperty(toolsets, "TargetFrameworkRootPath", paths.FrameworksDirectory + Path.DirectorySeparatorChar);              //NOTE: Must include trailing \
            if (!string.IsNullOrEmpty(paths.AndroidSdkDirectory))
            {
                SetProperty(toolsets, "AndroidSdkDirectory", paths.AndroidSdkDirectory);
            }
            if (!string.IsNullOrEmpty(paths.AndroidNdkDirectory))
            {
                SetProperty(toolsets, "AndroidNdkDirectory", paths.AndroidNdkDirectory);
            }

            var projectImportSearchPaths = toolsets.SelectSingleNode("projectImportSearchPaths");
            var searchPaths = projectImportSearchPaths.SelectSingleNode($"searchPaths[@os='{paths.SearchPathsOS}']") as XmlElement;

            if (searchPaths != null)
            {
                foreach (XmlNode property in searchPaths.SelectNodes("property[starts-with(@name, 'MSBuildExtensionsPath')]/@value"))
                {
                    property.Value = "";
                }
            }

            xml.Save(paths.XABuildConfig);

            if (Directory.Exists(paths.MSBuildSdksPath))
            {
                Environment.SetEnvironmentVariable("MSBuildSDKsPath", paths.MSBuildSdksPath, EnvironmentVariableTarget.Process);
            }
            Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", paths.MSBuildExeTempPath, EnvironmentVariableTarget.Process);
            return(xml);
        }
예제 #8
0
        static void CreateSdkResolverConfig(XABuildPaths paths)
        {
            if (string.IsNullOrEmpty(paths.SdkResolverConfigPath) || string.IsNullOrEmpty(paths.NuGetSdkResolverPath))
            {
                return;
            }
            var dir = Path.GetDirectoryName(paths.SdkResolverConfigPath);

            Directory.CreateDirectory(dir);
            using (var writer = File.CreateText(paths.SdkResolverConfigPath)) {
                writer.WriteLine("<SdkResolver>");
                writer.Write("\t<Path>");
                writer.Write(paths.NuGetSdkResolverPath);
                writer.WriteLine("</Path>");
                writer.WriteLine("</SdkResolver>");
            }
        }
예제 #9
0
        static StreamWriter OpenSysLinksFile(XABuildPaths paths)
        {
            string path = Path.Combine(paths.FrameworksDirectory, ".__sys_links.txt");

            //NOTE: on Windows, the NUnit tests can throw IOException when running xabuild in parallel
            for (int i = 0;; i++)
            {
                try {
                    return(File.AppendText(path));
                } catch (IOException) {
                    if (i == 2)
                    {
                        throw;                         //Fail after 3 tries
                    }
                    Thread.Sleep(100);
                }
            }
        }
예제 #10
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                CreateConfig(paths);

                //Create link to .NETFramework and .NETPortable directory
                foreach (var dir in Directory.GetDirectories(paths.SystemProfiles))
                {
                    var name = Path.GetFileName(dir);
                    if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir))
                    {
                        return(1);
                    }
                }

                return(MSBuildApp.Main());
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
예제 #11
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                var xml = CreateConfig(paths);

                //Create link to .NETFramework and .NETPortable directory
                foreach (var dir in Directory.GetDirectories(paths.SystemProfiles))
                {
                    var name = Path.GetFileName(dir);
                    if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir))
                    {
                        return(1);
                    }

                    //NOTE: on Windows, the NUnit tests can throw IOException when running xabuild in parallel
                    for (int i = 0;; i++)
                    {
                        try {
                            File.AppendAllText(Path.Combine(paths.FrameworksDirectory, ".__sys_links.txt"), name + "\n");
                            break;
                        } catch (IOException) {
                            if (i == 2)
                            {
                                throw;                                 //Fail after 3 tries
                            }
                            Thread.Sleep(100);
                        }
                    }
                }

                int exitCode = MSBuildApp.Main();
                if (exitCode != 0)
                {
                    Console.WriteLine($"MSBuildApp.Main exited with {exitCode}, xabuild configuration is:");

                    var settings = new XmlWriterSettings {
                        Indent = true,
                        NewLineOnAttributes = true,
                    };
                    using (var writer = XmlTextWriter.Create(Console.Out, settings)) {
                        xml.WriteTo(writer);
                    }
                }
                return(exitCode);
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }
예제 #12
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                //HACK: running on Mono, MSBuild cannot resolve System.Reflection.Metadata
                if (!paths.IsWindows)
                {
                    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
                        var name = new AssemblyName(args.Name);
                        if (name.Name == "System.Reflection.Metadata")
                        {
                            var path = Path.Combine(paths.MSBuildBin, $"{name.Name}.dll");
                            return(Assembly.LoadFile(path));
                        }
                        //Return null, to revert to default .NET behavior
                        return(null);
                    };
                }
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                // Create a custom xabuild.exe.config
                CreateConfig(paths);
                // Create a Microsoft.Build.NuGetSdkResolver.xml
                CreateSdkResolverConfig(paths);

                //Symbolic links to be created: key=in-tree-dir, value=system-dir
                var symbolicLinks = new Dictionary <string, string> ();
                if (paths.IsMacOS || paths.IsLinux)
                {
                    foreach (var dir in Directory.EnumerateDirectories(paths.MonoSystemFrameworkRoot))
                    {
                        if (Path.GetFileName(dir).EndsWith("-api", StringComparison.OrdinalIgnoreCase))
                        {
                            var inTreeFramework = Path.Combine(paths.XamarinAndroidBuildOutput, "lib", "xamarin.android", Path.GetFileName(dir));
                            symbolicLinks [inTreeFramework] = dir;
                        }
                    }
                }
                foreach (var dir in Directory.EnumerateDirectories(paths.SystemFrameworks))
                {
                    if (Path.GetFileName(dir) != "MonoAndroid")
                    {
                        var inTreeFramework = Path.Combine(paths.FrameworksDirectory, Path.GetFileName(dir));
                        symbolicLinks [inTreeFramework] = dir;
                    }
                }
                foreach (var dir in paths.SystemTargetsDirectories)
                {
                    var inTreeTargetsDir = Path.Combine(paths.MSBuildExtensionsPath, Path.GetFileName(dir));
                    if (!symbolicLinks.ContainsKey(inTreeTargetsDir))
                    {
                        symbolicLinks [inTreeTargetsDir] = dir;
                        continue;
                    }
                    var prevTargetDir = symbolicLinks [inTreeTargetsDir];
                    symbolicLinks.Remove(inTreeTargetsDir);
                    if (Directory.Exists(inTreeTargetsDir) && SymbolicLink.IsPathSymlink(inTreeTargetsDir))
                    {
                        Console.WriteLine($"Removing old symlink: {inTreeTargetsDir}");
                        Directory.Delete(inTreeTargetsDir);
                    }
                    var subTargetDirs = Directory.EnumerateDirectories(prevTargetDir)
                                        .Concat(Directory.EnumerateDirectories(dir));
                    foreach (var subDir in subTargetDirs)
                    {
                        var inTreeTargetSubdir = Path.Combine(inTreeTargetsDir, Path.GetFileName(subDir));
                        symbolicLinks [inTreeTargetSubdir] = subDir;
                    }
                }
                if (symbolicLinks.Keys.Any(d => !Directory.Exists(d)))
                {
                    //Hold open the file while creating the symbolic links
                    using (var writer = OpenSysLinksFile(paths)) {
                        foreach (var pair in symbolicLinks)
                        {
                            var systemDirectory = pair.Value;
                            var symbolicLink    = pair.Key;
                            Console.WriteLine($"[xabuild] creating symbolic link '{symbolicLink}' -> '{systemDirectory}'");
                            if (!SymbolicLink.Create(symbolicLink, systemDirectory))
                            {
                                return(1);
                            }
                            writer.WriteLine(Path.GetFileName(symbolicLink));
                        }
                    }
                }

                return(MSBuildApp.Main());
            } finally {
                //NOTE: this is a temporary directory
                Directory.Delete(paths.MSBuildTempPath, recursive: true);
            }
        }
예제 #13
0
        static int Main()
        {
            var paths = new XABuildPaths();

            try {
                //HACK: running on Mono, MSBuild cannot resolve System.Reflection.Metadata
                if (!paths.IsWindows)
                {
                    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
                        var name = new AssemblyName(args.Name);
                        if (name.Name == "System.Reflection.Metadata")
                        {
                            var path = Path.Combine(paths.MSBuildBin, $"{name.Name}.dll");
                            return(Assembly.LoadFile(path));
                        }
                        //Return null, to revert to default .NET behavior
                        return(null);
                    };
                }
                if (!Directory.Exists(paths.XamarinAndroidBuildOutput))
                {
                    Console.WriteLine($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
                    return(1);
                }

                //Create a custom xabuild.exe.config
                var xml = CreateConfig(paths);

                //Symbolic links to be created: key=system, value=in-tree
                var symbolicLinks = new Dictionary <string, string> ();
                foreach (var dir in Directory.EnumerateDirectories(paths.SystemFrameworks))
                {
                    if (Path.GetFileName(dir) != "MonoAndroid")
                    {
                        symbolicLinks [dir] = Path.Combine(paths.FrameworksDirectory, Path.GetFileName(dir));
                    }
                }
                foreach (var dir in paths.SystemTargetsDirectories)
                {
                    symbolicLinks [dir] = Path.Combine(paths.MSBuildExtensionsPath, Path.GetFileName(dir));
                }
                if (symbolicLinks.Values.Any(d => !Directory.Exists(d)))
                {
                    //Hold open the file while creating the symbolic links
                    using (var writer = OpenSysLinksFile(paths)) {
                        foreach (var pair in symbolicLinks)
                        {
                            var systemDirectory = pair.Key;
                            var symbolicLink    = pair.Value;
                            Console.WriteLine($"[xabuild] creating symbolic link '{symbolicLink}' -> '{systemDirectory}'");
                            if (!SymbolicLink.Create(symbolicLink, systemDirectory))
                            {
                                return(1);
                            }
                            writer.WriteLine(Path.GetFileName(symbolicLink));
                        }
                    }
                }

                return(MSBuildApp.Main());
            } finally {
                //NOTE: these are temporary files
                foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig })
                {
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                }
            }
        }