public XmlDocument GenerateForSelectSolution(List <XmlDocument> definitions, string platform, List <Service> services)
        {
            var doc = new XmlDocument();

            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "UTF-8", null));
            var input = doc.CreateElement("Input");

            doc.AppendChild(input);

            input.AppendChild(this.m_ServiceInputGenerator.Generate(doc, null, services));

            var generation   = doc.CreateElement("Generation");
            var platformName = doc.CreateElement("Platform");

            platformName.AppendChild(doc.CreateTextNode(platform));
            var hostPlatformName = doc.CreateElement("HostPlatform");

            hostPlatformName.AppendChild(doc.CreateTextNode(_hostPlatformDetector.DetectPlatform()));
            generation.AppendChild(platformName);
            generation.AppendChild(hostPlatformName);
            input.AppendChild(generation);

            var featuresNode = doc.CreateElement("Features");

            foreach (var feature in _featureManager.GetAllEnabledFeatures())
            {
                var featureNode = doc.CreateElement(feature.ToString());
                featureNode.AppendChild(doc.CreateTextNode("True"));
                featuresNode.AppendChild(featureNode);
            }
            input.AppendChild(featuresNode);

            var projects = doc.CreateElement("Projects");

            input.AppendChild(projects);
            foreach (var projectDoc in definitions)
            {
                if (this.m_ExcludedServiceAwareProjectDetector.IsExcludedServiceAwareProject(
                        projectDoc.DocumentElement.GetAttribute("Name"),
                        projectDoc,
                        services))
                {
                    continue;
                }

                projects.AppendChild(doc.ImportNode(
                                         projectDoc.DocumentElement,
                                         true));
            }
            return(doc);
        }
예제 #2
0
        public int Execute(Execution execution)
        {
            var module = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

            if (module.Packages == null)
            {
                throw new InvalidOperationException("No such package has been added");
            }

            var package = _packageUrlParser.Parse(execution.PackageUrl);

            var packageRef = _packageNameLookup.LookupPackageByName(module, package.Uri);

            _packageManager.Resolve(
                execution.WorkingDirectory,
                module,
                packageRef,
                execution.Platform ?? _hostPlatformDetector.DetectPlatform(),
                null,
                null,
                true,
                execution.SafePackageResolution);

            return(0);
        }
        public int Execute(Execution execution)
        {
            var module = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

            if (module.Packages == null)
            {
                return(0);
            }

            var platform = execution.Platform ?? _hostPlatformDetector.DetectPlatform();

            foreach (var package in module.Packages)
            {
                _packageManager.Resolve(
                    execution.WorkingDirectory,
                    module,
                    package,
                    platform,
                    null,
                    null,
                    true,
                    execution.SafePackageResolution);
            }

            return(0);
        }
예제 #4
0
        public int Execute(Execution execution)
        {
            var url    = execution.PackageUrl;
            var module = ModuleInfo.Load(Path.Combine("Build", "Module.xml"));

            if (module.Packages == null)
            {
                throw new InvalidOperationException("No such package has been added");
            }

            var branch = "master";

            if (url.LastIndexOf('@') > url.LastIndexOf('/'))
            {
                // A branch / commit ref is specified.
                branch = url.Substring(url.LastIndexOf('@') + 1);
                url    = url.Substring(0, url.LastIndexOf('@'));
            }

            var packageRef = _packageNameLookup.LookupPackageByName(module, url);

            _packageManager.Resolve(
                module,
                packageRef,
                execution.Platform ?? _hostPlatformDetector.DetectPlatform(),
                null,
                null,
                true);

            return(0);
        }
예제 #5
0
        public void ScanPackageForToolsAndInstall(string toolFolder)
        {
            var projectsPath = Path.Combine(toolFolder, "Build", "Projects");
            var projectsInfo = new DirectoryInfo(projectsPath);

            foreach (var file in projectsInfo.GetFiles("*.definition"))
            {
                var document = XDocument.Load(file.FullName);
                var tools    = document.XPathSelectElements("/ExternalProject/Tool");

                foreach (var tool in tools)
                {
                    var toolPath = Path.Combine(toolFolder, tool.Attribute(XName.Get("Path")).Value);
                    var toolName = tool.Attribute(XName.Get("Name")).Value;

                    if (Path.DirectorySeparatorChar == '\\')
                    {
                        toolPath = toolPath.Replace("/", "\\");
                    }
                    else if (Path.DirectorySeparatorChar == '/')
                    {
                        toolPath = toolPath.Replace("\\", "/");
                    }

                    using (var writer = new StreamWriter(Path.Combine(this.GetToolsPath(), toolName + ".tool")))
                    {
                        writer.WriteLine(toolPath);
                    }

                    Console.WriteLine("Global tool '" + toolName + "' now points to '" + toolPath + "'");

                    if (_hostPlatformDetector.DetectPlatform() == "Windows")
                    {
                        this.InstallToolIntoWindowsStartMenu(toolName, toolPath);
                    }
                    else if (_hostPlatformDetector.DetectPlatform() == "MacOS")
                    {
                        this.InstallToolIntoUserApplicationFolder(toolName, toolPath);
                    }
                    else if (_hostPlatformDetector.DetectPlatform() == "Linux")
                    {
                        this.InstallToolIntoLinuxApplicationMenu(toolName, toolPath);
                    }
                }
            }
        }
예제 #6
0
        public string GetFileSuffix(Language language)
        {
            switch (language)
            {
            case Language.CSharp:
                return("CSharp");

            case Language.CPlusPlus:
                if (_hostPlatformDetector.DetectPlatform() == "Windows")
                {
                    return("CPlusPlus.VisualStudio");
                }
                else
                {
                    return("CPlusPlus.MonoDevelop");
                }

            default:
                throw new NotSupportedException();
            }
        }
예제 #7
0
        public string GetToolExecutablePath(string toolName)
        {
            var executableFile = _packageGlobalTool.ResolveGlobalToolIfPresent(toolName);

            if (executableFile == null && _knownTools.ContainsKey(toolName.ToLowerInvariant()))
            {
                var package = new PackageRef
                {
                    Uri    = _knownTools[toolName.ToLowerInvariant()],
                    GitRef = "master",
                    Folder = null
                };

                RedirectableConsole.WriteLine("Installing {0}...", _knownTools[toolName.ToLowerInvariant()]);
                _packageManager.Resolve(Environment.CurrentDirectory, null, package, _hostPlatformDetector.DetectPlatform(), null, false, true, false);
            }
            else
            {
                return(executableFile);
            }

            return(_packageGlobalTool.ResolveGlobalToolIfPresent(toolName));
        }
예제 #8
0
        public int Execute(Execution execution)
        {
            var    hostPlatform          = _hostPlatformDetector.DetectPlatform();
            string builderPathNativeArch = null;
            string builderPath64         = null;
            string builderPath32         = null;
            var    extraArgsNativeArch   = string.Empty;
            var    extraArgs64           = string.Empty;
            var    extraArgs32           = string.Empty;
            var    extraArgsGeneral      = string.Empty;

            var targetPlatforms = (execution.Platform ?? hostPlatform).Split(',');
            var module          = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

            if (hostPlatform == "Windows")
            {
                // Newer installs of Visual Studio (like 2017) don't create registry entries for MSBuild, so we have to
                // use a tool called vswhere in order to find MSBuild on these systems.  This call will implicitly install
                // the vswhere package if it's not already installed.
                var           vswhere       = _knownToolProvider.GetToolExecutablePath("vswhere");
                List <string> installations = null;
                if (vswhere != null && File.Exists(vswhere))
                {
                    try
                    {
                        var processStartInfo = new ProcessStartInfo();
                        processStartInfo.FileName               = vswhere;
                        processStartInfo.Arguments              = "-products * -requires Microsoft.Component.MSBuild -property installationPath";
                        processStartInfo.UseShellExecute        = false;
                        processStartInfo.RedirectStandardOutput = true;
                        var process             = Process.Start(processStartInfo);
                        var installationsString = process.StandardOutput.ReadToEnd();
                        installations = installationsString.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
                        process.WaitForExit();

                        if (process.ExitCode != 0)
                        {
                            RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations (non-zero exit code from vswhere)");
                        }
                    }
                    catch (Exception ex)
                    {
                        RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations: " + ex.Message);
                    }
                }

                if (installations != null)
                {
                    // Check if MSBuild is present in any of those installation paths.
                    foreach (var basePath in installations)
                    {
                        var msbuildLocation = Path.Combine(basePath, "MSBuild\\15.0\\Bin\\MSBuild.exe");
                        if (File.Exists(msbuildLocation))
                        {
                            builderPathNativeArch = msbuildLocation;
                            extraArgsNativeArch   = "/m /nodeReuse:false ";
                            builderPath32         = msbuildLocation;
                            extraArgs32           = "/m /nodeReuse:false ";

                            var x64Location = Path.Combine(basePath, "MSBuild\\15.0\\Bin\\amd64\\MSBuild.exe");
                            if (File.Exists(x64Location))
                            {
                                builderPath64 = x64Location;
                                extraArgs64   = "/m /nodeReuse:false ";
                            }

                            break;
                        }
                    }
                }

                if (builderPathNativeArch == null)
                {
                    // Try to find via the registry.
                    foreach (var arch in new[] { RegistryView.Default, RegistryView.Registry32, RegistryView.Registry64 })
                    {
                        // Find latest version of MSBuild.
                        var registryKey =
                            RegistryKey.OpenBaseKey(
                                RegistryHive.LocalMachine,
                                arch)
                            .OpenSubKey("SOFTWARE")?
                            .OpenSubKey("Microsoft")?
                            .OpenSubKey("MSBuild")?
                            .OpenSubKey("ToolsVersions");
                        if (registryKey == null)
                        {
                            if (arch == RegistryView.Registry64)
                            {
                                continue;
                            }

                            RedirectableConsole.ErrorWriteLine(
                                "ERROR: No versions of MSBuild were available " +
                                "according to the registry (or they were not readable).");
                            return(1);
                        }

                        var subkeys         = registryKey.GetSubKeyNames();
                        var orderedVersions =
                            subkeys.OrderByDescending(x => int.Parse(x.Split('.').First(), CultureInfo.InvariantCulture));
                        var builderPath = (from version in orderedVersions
                                           let path = (string)registryKey.OpenSubKey(version)?.GetValue("MSBuildToolsPath")
                                                      where path != null && Directory.Exists(path)
                                                      let msbuild = Path.Combine(path, "MSBuild.exe")
                                                                    where File.Exists(msbuild)
                                                                    select msbuild).FirstOrDefault();

                        if (builderPath == null)
                        {
                            if (arch == RegistryView.Registry64)
                            {
                                continue;
                            }

                            RedirectableConsole.ErrorWriteLine(
                                "ERROR: Unable to find installed MSBuild in any installed tools version.");
                            return(1);
                        }

                        var extraArgs = string.Empty;
                        if (!builderPath.Contains("v2.0.50727"))
                        {
                            extraArgs = "/m /nodeReuse:false ";
                        }

                        switch (arch)
                        {
                        case RegistryView.Default:
                            builderPathNativeArch = builderPath;
                            extraArgsNativeArch   = extraArgs;
                            break;

                        case RegistryView.Registry32:
                            builderPath32 = builderPath;
                            extraArgs32   = extraArgs;
                            break;

                        case RegistryView.Registry64:
                            builderPath64 = builderPath;
                            extraArgs64   = extraArgs;
                            break;
                        }
                    }
                }
            }
            else
            {
                // Find path to xbuild.
                var whichPaths = new[] { "/bin/which", "/usr/bin/which" };

                // We can only use the new MSBuild tool if no projects are C++ projects on Mac or Linux.
                var isAnyNativeProject = false;
                foreach (var def in module.GetDefinitionsRecursively())
                {
                    var document     = XDocument.Load(def.DefinitionPath);
                    var languageAttr = document?.Root?.Attributes()?.FirstOrDefault(x => x.Name.LocalName == "Language");
                    if (languageAttr != null && languageAttr.Value == "C++")
                    {
                        isAnyNativeProject = true;
                        break;
                    }
                }
                if (!isAnyNativeProject)
                {
                    foreach (var w in whichPaths)
                    {
                        if (File.Exists(w))
                        {
                            var whichProcess = Process.Start(new ProcessStartInfo(w, "msbuild")
                            {
                                RedirectStandardOutput = true,
                                UseShellExecute        = false
                            });
                            if (whichProcess == null)
                            {
                                continue;
                            }
                            var result = whichProcess.StandardOutput.ReadToEnd().Trim();
                            if (!string.IsNullOrWhiteSpace(result) && File.Exists(result))
                            {
                                builderPathNativeArch = result;
                                break;
                            }
                        }
                    }
                }

                if (builderPathNativeArch == null)
                {
                    foreach (var w in whichPaths)
                    {
                        if (File.Exists(w))
                        {
                            var whichProcess = Process.Start(new ProcessStartInfo(w, "xbuild")
                            {
                                RedirectStandardOutput = true,
                                UseShellExecute        = false
                            });
                            if (whichProcess == null)
                            {
                                continue;
                            }
                            var result = whichProcess.StandardOutput.ReadToEnd().Trim();
                            if (!string.IsNullOrWhiteSpace(result) && File.Exists(result))
                            {
                                builderPathNativeArch = result;
                                break;
                            }
                        }
                    }
                }

                if (builderPathNativeArch == null && _hostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/xbuild"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find xbuild with the which tool, manually set the
                    // path here in an attempt to find it.
                    builderPathNativeArch = "/usr/local/bin/xbuild";
                }

                if (builderPathNativeArch == null)
                {
                    RedirectableConsole.ErrorWriteLine("ERROR: Unable to find msbuild or xbuild on the current PATH.");
                    return(1);
                }

                builderPath32 = builderPathNativeArch;
                builderPath64 = builderPathNativeArch;
            }

            if (!string.IsNullOrWhiteSpace(execution.BuildTarget))
            {
                extraArgsGeneral += "/t:\"" + execution.BuildTarget + "\" ";
            }
            foreach (var prop in execution.BuildProperties)
            {
                extraArgsGeneral += "/p:\"" + prop.Key.Replace("\"", "\\\"") + "\"=\"" + (prop.Value ?? string.Empty).Replace("\"", "\\\"") + "\" ";
            }

            switch (execution.BuildProcessArchitecture)
            {
            case "x86":
                RedirectableConsole.WriteLine("INFO: Using " + builderPath32 + " (forced 32-bit) to perform this build.");
                break;

            case "x64":
                RedirectableConsole.WriteLine("INFO: Using " + builderPath64 + " (forced 64-bit) to perform this build.");
                break;

            case "Default":
            default:
                RedirectableConsole.WriteLine("INFO: Using " + builderPathNativeArch + " (32-bit: " + builderPath32 + ") to perform this build.");
                break;
            }

            foreach (var platform in targetPlatforms)
            {
                string builderPath;
                string extraArgs;

                switch (execution.BuildProcessArchitecture)
                {
                case "x86":
                    builderPath = builderPath32;
                    extraArgs   = extraArgs32 + extraArgsGeneral;
                    break;

                case "x64":
                    builderPath = builderPath64;
                    extraArgs   = extraArgs64 + extraArgsGeneral;
                    break;

                case "Default":
                default:
                    builderPath = platform == "WindowsPhone" ? builderPath32 : builderPathNativeArch;
                    extraArgs   = (platform == "WindowsPhone" ? extraArgs32 : extraArgsNativeArch) + extraArgsGeneral;
                    break;
                }

                var fileToBuild = module.Name + "." + platform + ".sln";

                RedirectableConsole.WriteLine("INFO: Executing " + builderPath + " with arguments: " + extraArgs + fileToBuild);

                var process =
                    Process.Start(new ProcessStartInfo(builderPath, extraArgs + fileToBuild)
                {
                    UseShellExecute = false
                });
                if (process == null)
                {
                    RedirectableConsole.ErrorWriteLine("ERROR: Build process did not start successfully.");
                    return(1);
                }
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            return(0);
        }
예제 #9
0
        public void ResolveAll(string workingDirectory, ModuleInfo module, string platform, bool?enableParallelisation, bool forceUpgrade, bool?safeResolve)
        {
            if (!_featureManager.IsFeatureEnabled(Feature.PackageManagement))
            {
                return;
            }

            RedirectableConsole.WriteLine("Starting resolution of packages for " + platform + "...");

            var parallelisation = enableParallelisation ?? _hostPlatformDetector.DetectPlatform() == "Windows";

            if (parallelisation)
            {
                RedirectableConsole.WriteLine("Enabled parallelisation; use --no-parallel to disable...");
            }

            if (module.Packages != null && module.Packages.Count > 0)
            {
                var taskList   = new List <Task <Tuple <string, Action> > >();
                var resultList = new List <Tuple <string, Action> >();
                foreach (var submodule in module.Packages)
                {
                    if (submodule.IsActiveForPlatform(platform))
                    {
                        RedirectableConsole.WriteLine("Querying: " + submodule.Uri);
                        var submodule1 = submodule;
                        if (parallelisation)
                        {
                            var task = new Func <Task <Tuple <string, Action> > >(async() =>
                            {
                                var metadata = await Task.Run(() =>
                                                              Lookup(workingDirectory, module, submodule1, platform, null, null, forceUpgrade, safeResolve));
                                if (metadata == null)
                                {
                                    return(new Tuple <string, Action>(submodule1.Uri, () => { }));
                                }
                                return(new Tuple <string, Action>(submodule1.Uri,
                                                                  () => { this.Resolve(workingDirectory, metadata, submodule1, null, null, forceUpgrade, safeResolve); }));
                            });
                            taskList.Add(task());
                        }
                        else
                        {
                            var metadata = Lookup(workingDirectory, module, submodule1, platform, null, null, forceUpgrade, safeResolve);
                            if (metadata == null)
                            {
                                resultList.Add(new Tuple <string, Action>(submodule1.Uri, () => { }));
                            }
                            else
                            {
                                resultList.Add(new Tuple <string, Action>(submodule1.Uri,
                                                                          () => { this.Resolve(workingDirectory, metadata, submodule1, null, null, forceUpgrade, safeResolve); }));
                            }
                        }
                    }
                    else
                    {
                        RedirectableConsole.WriteLine("Skipping resolution for " + submodule.Uri + " because it is not active for this target platform");
                    }
                }

                if (parallelisation)
                {
                    var taskArray = taskList.ToArray();
                    Task.WaitAll(taskArray);
                    foreach (var tuple in taskArray)
                    {
                        RedirectableConsole.WriteLine("Resolving: " + tuple.Result.Item1);
                        tuple.Result.Item2();
                    }
                }
                else
                {
                    foreach (var tuple in resultList)
                    {
                        RedirectableConsole.WriteLine("Resolving: " + tuple.Item1);
                        tuple.Item2();
                    }
                }
            }

            foreach (var submodule in module.GetSubmodules(platform))
            {
                if (submodule.Packages.Count == 0 && submodule.GetSubmodules(platform).Length == 0)
                {
                    if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule, Feature.OptimizationSkipResolutionOnNoPackagesOrSubmodules))
                    {
                        RedirectableConsole.WriteLine(
                            "Skipping package resolution in submodule for " + submodule.Name + " (there are no submodule or packages)");
                        continue;
                    }
                }

                RedirectableConsole.WriteLine(
                    "Invoking package resolution in submodule for " + submodule.Name);
                string parallelMode = null;
                if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule, Feature.TaskParallelisation))
                {
                    if (parallelisation)
                    {
                        parallelMode += "-parallel ";
                    }
                    else
                    {
                        parallelMode += "-no-parallel ";
                    }
                }
                _moduleExecution.RunProtobuild(
                    submodule,
                    _featureManager.GetFeatureArgumentToPassToSubmodule(module, submodule) + parallelMode +
                    "-resolve " + platform + " " + packageRedirector.GetRedirectionArguments());
                RedirectableConsole.WriteLine(
                    "Finished submodule package resolution for " + submodule.Name);
            }

            RedirectableConsole.WriteLine("Package resolution complete.");
        }
예제 #10
0
        /// <summary>
        /// Generates a project at the target path.
        /// </summary>
        /// <param name="current">The current project to generate.</param>
        /// <param name="definitions">A list of all loaded project definitions.</param>
        /// <param name="workingDirectory"></param>
        /// <param name="rootPath">The module root path, with directory seperator appended.</param>
        /// <param name="projectName">The project name.</param>
        /// <param name="platformName">The platform name.</param>
        /// <param name="services">A list of services.</param>
        /// <param name="packagesFilePath">
        ///     Either the full path to the packages.config for the
        ///     generated project if it exists, or an empty string.
        /// </param>
        /// <param name="onActualGeneration"></param>
        /// <param name="debugProjectGeneration">Whether to emit a .input file for XSLT debugging.</param>
        public void Generate(
            DefinitionInfo current,
            List <LoadedDefinitionInfo> definitions,
            string workingDirectory,
            string rootPath,
            string projectName,
            string platformName,
            List <Service> services,
            out string packagesFilePath,
            Action onActualGeneration,
            bool debugProjectGeneration)
        {
            packagesFilePath = string.Empty;

            // Work out what document this is.
            var projectDoc = definitions.First(
                x => x.Project.DocumentElement.Attributes["Name"].Value == projectName)?.Project;

            // Check to see if we have a Project node; don't process it.
            if (projectDoc?.DocumentElement == null)
            {
                return;
            }

            // If this is a custom project, run any custom generation commands for
            // the current host and target platform.
            if (projectDoc.DocumentElement.Name == "CustomProject")
            {
                onActualGeneration();

                var onGenerateElements = projectDoc.DocumentElement.SelectNodes("OnGenerate");
                if (onGenerateElements != null)
                {
                    foreach (var onGenerateElement in onGenerateElements.OfType <XmlElement>())
                    {
                        var matches    = true;
                        var hostName   = onGenerateElement.GetAttribute("HostName");
                        var targetName = onGenerateElement.GetAttribute("TargetName");

                        if (!string.IsNullOrWhiteSpace(hostName))
                        {
                            if (hostName != _hostPlatformDetector.DetectPlatform())
                            {
                                matches = false;
                            }
                        }

                        if (!string.IsNullOrWhiteSpace(targetName))
                        {
                            if (targetName != platformName)
                            {
                                matches = false;
                            }
                        }

                        if (matches)
                        {
                            var command   = onGenerateElement.SelectSingleNode("Command")?.InnerText.Trim();
                            var arguments = onGenerateElement.SelectSingleNode("Arguments")?.InnerText.Trim() ?? string.Empty;

                            if (!string.IsNullOrWhiteSpace(command))
                            {
                                var workingPath = Path.Combine(
                                    rootPath,
                                    projectDoc.DocumentElement.Attributes["Path"].Value);
                                var resolvedCommandPath = Path.Combine(
                                    workingPath,
                                    command);

                                if (File.Exists(resolvedCommandPath))
                                {
                                    var process =
                                        Process.Start(new ProcessStartInfo(resolvedCommandPath, arguments)
                                    {
                                        WorkingDirectory = workingPath,
                                        UseShellExecute  = false
                                    });
                                    if (process == null)
                                    {
                                        RedirectableConsole.ErrorWriteLine("ERROR: Process did not start when running " + resolvedCommandPath + " " +
                                                                           arguments);
                                        ExecEnvironment.Exit(1);
                                        return;
                                    }
                                    process.WaitForExit();
                                    if (process.ExitCode != 0)
                                    {
                                        RedirectableConsole.ErrorWriteLine(
                                            "ERROR: Non-zero exit code " + process.ExitCode);
                                        ExecEnvironment.Exit(1);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // If this is not a normal project at this point, don't process it.
            if (projectDoc.DocumentElement.Name != "Project")
            {
                return;
            }

            // Load the appropriate project transformation XSLT.
            var languageAttribute = projectDoc.DocumentElement.Attributes["Language"];
            var languageText      = languageAttribute != null ? languageAttribute.Value : "C#";
            var language          = this.m_LanguageStringProvider.GetLanguageFromConfigurationName(languageText);
            var projectTransform  = this.m_ResourceProvider.LoadXSLT(workingDirectory, ResourceType.GenerateProject, language, platformName);

            // Work out what platforms this project should be generated for.
            var platformAttribute = projectDoc.DocumentElement.Attributes["Platforms"];

            string[] allowedPlatforms = null;
            if (platformAttribute != null)
            {
                allowedPlatforms = platformAttribute.Value
                                   .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                   .Select(x => x.Trim())
                                   .ToArray();
            }

            // Filter on allowed platforms.
            if (allowedPlatforms != null)
            {
                var allowed = false;
                foreach (var platform in allowedPlatforms)
                {
                    if (string.Compare(platformName, platform, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        allowed = true;
                        break;
                    }
                }
                if (!allowed)
                {
                    return;
                }
            }

            // If the project has a <Services> node, but there are no entries in /Input/Services,
            // then nothing depends on this service (if there is a <Reference> to this project, it will
            // use the default service).  So for service-aware projects without any services being
            // referenced, we exclude them from the generation.
            if (this.m_ExcludedServiceAwareProjectDetector.IsExcludedServiceAwareProject(
                    projectDoc.DocumentElement.Attributes["Name"].Value,
                    projectDoc,
                    services))
            {
                return;
            }

            // Inform the user we're generating this project.
            onActualGeneration();

            // Add include projects if they have an AppliesTo tag that matches this project's name.
            this._includeProjectAppliesToUpdater.UpdateProjectReferences(definitions.Select(x => x.Project).ToList(), projectDoc);

            // Add references and properties from include projects.
            _includeProjectMerger.MergeInReferencesAndPropertiesForIncludeProjects(definitions, projectDoc, platformName);

            // Imply external project references from other external projects.  We do
            // this so that external projects can reference other external projects (which
            // we can't reasonably handle at the XSLT level since it's recursive).
            this.m_ExternalProjectReferenceResolver.ResolveExternalProjectReferences(definitions, projectDoc, platformName);

            // Generate Info.plist files if necessary (for Mac / iOS).
            this._mPlatformResourcesGenerator.GenerateInfoPListIfNeeded(definitions, current, projectDoc, platformName);

            // Work out what path to save at.
            var path = Path.Combine(
                rootPath,
                projectDoc.DocumentElement.Attributes["Path"].Value
                .Replace('\\', Path.DirectorySeparatorChar)
                .Replace('/', Path.DirectorySeparatorChar),
                projectDoc.DocumentElement.Attributes["Name"].Value + "." +
                platformName + "." + this.m_LanguageStringProvider.GetProjectExtension(language));

            // Make sure that the directory exists where the file will be stored.
            var targetFile = new FileInfo(path);

            if (!targetFile.Directory.Exists)
            {
                targetFile.Directory.Create();
            }

            path = targetFile.FullName;

            // Handle NuGet packages.config early so that it'll be in place
            // when the generator automatically determined dependencies.
            this.m_NuGetConfigMover.Move(rootPath, platformName, projectDoc);

            // Work out what path the NuGet packages.config might be at.
            var packagesFile = new FileInfo(
                Path.Combine(
                    rootPath,
                    projectDoc.DocumentElement.Attributes["Path"].Value
                    .Replace('\\', Path.DirectorySeparatorChar)
                    .Replace('/', Path.DirectorySeparatorChar),
                    "packages.config"));

            // Generate the input document.
            var input = this.m_ProjectInputGenerator.Generate(
                definitions.Select(x => x.Project).ToList(),
                workingDirectory,
                rootPath,
                projectName,
                platformName,
                packagesFile.FullName,
                projectDoc.DocumentElement.ChildNodes
                .OfType <XmlElement>()
                .Where(x => x.Name.ToLower() == "properties")
                .SelectMany(x => x.ChildNodes
                            .OfType <XmlElement>()),
                services);

            var settings = new XmlWriterSettings();

            settings.Indent = true;

            if (debugProjectGeneration)
            {
                using (var writer = XmlWriter.Create(path + ".input", settings))
                {
                    input.Save(writer);
                }
            }

            // Transform the input document using the XSLT transform.
            using (var writer = XmlWriter.Create(path, settings))
            {
                projectTransform.Transform(input, writer);
            }

            // Also remove any left over .sln or .userprefs files.
            var slnPath = Path.Combine(
                rootPath,
                projectDoc.DocumentElement.Attributes["Path"].Value,
                projectDoc.DocumentElement.Attributes["Name"].Value + "." +
                platformName + ".sln");
            var userprefsPath = Path.Combine(
                rootPath,
                projectDoc.DocumentElement.Attributes["Path"].Value,
                projectDoc.DocumentElement.Attributes["Name"].Value + "." +
                platformName + ".userprefs");

            if (File.Exists(slnPath))
            {
                File.Delete(slnPath);
            }
            if (File.Exists(userprefsPath))
            {
                File.Delete(userprefsPath);
            }

            // Only return the package file path if it exists.
            if (packagesFile.Exists)
            {
                packagesFilePath = packagesFile.FullName;
            }
        }
예제 #11
0
        public int Execute(Execution execution)
        {
            var assemblyPath = Assembly.GetEntryAssembly().Location;
            var fileInfo     = new FileInfo(assemblyPath);
            var modulePath   = fileInfo.DirectoryName;

            if (modulePath == null)
            {
                RedirectableConsole.WriteLine(
                    "Unable to determine the location of Protobuild.");
                return(1);
            }

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                modulePath = execution.WorkingDirectory;
            }

            string executablePath     = null;
            var    executableIsNative = false;

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                // We can only run global tools.
                var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                if (globalToolPath == null)
                {
                    RedirectableConsole.WriteLine(
                        "There is no global tool registered as '" + execution.ExecuteProjectName + "'");
                    return(1);
                }
                else
                {
                    executablePath     = globalToolPath;
                    executableIsNative = m_HostPlatformDetector.DetectPlatform() == "MacOS" && globalToolPath.EndsWith(".app");
                }
            }
            else
            {
                var platform    = this.m_HostPlatformDetector.DetectPlatform();
                var module      = ModuleInfo.Load(Path.Combine(modulePath, "Build", "Module.xml"));
                var definitions = module.GetDefinitionsRecursively(platform).ToList();
                var target      = definitions.FirstOrDefault(x => x.Name == execution.ExecuteProjectName);
                if (target == null)
                {
                    // Check to see if there is any external project definition that provides the tool.
                    foreach (var definition in definitions)
                    {
                        var document = XDocument.Load(definition.DefinitionPath);
                        if (document.Root.Name.LocalName == "ExternalProject")
                        {
                            foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                            {
                                var name = node.Attribute(XName.Get("Name")).Value;
                                var path = node.Attribute(XName.Get("Path")).Value;

                                if (name == execution.ExecuteProjectName)
                                {
                                    executablePath = Path.Combine(definition.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                    break;
                                }
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            RedirectableConsole.WriteLine(
                                "There is no project definition with name '" + execution.ExecuteProjectName + "'");
                            return(1);
                        }
                        else
                        {
                            executablePath     = globalToolPath;
                            executableIsNative = m_HostPlatformDetector.DetectPlatform() == "MacOS" && globalToolPath.EndsWith(".app");
                        }
                    }
                }
                else
                {
                    var document = XDocument.Load(target.DefinitionPath);
                    if (document.Root.Name.LocalName == "Project")
                    {
                        var    assemblyName       = this.m_ProjectOutputPathCalculator.GetProjectAssemblyName(platform, target, document);
                        var    prefixPath         = this.m_ProjectOutputPathCalculator.GetProjectOutputPathPrefix(platform, target, document, false);
                        var    directory          = new DirectoryInfo(Path.Combine(modulePath, prefixPath));
                        var    subdirectories     = directory.GetDirectories();
                        var    preferredName      = (execution.ExecuteProjectConfiguration ?? "Debug").ToLowerInvariant();
                        var    preferredDirectory = subdirectories.FirstOrDefault(x => x.Name.ToLowerInvariant() == preferredName);
                        var    targetName         = assemblyName + ".exe";
                        string targetAppName      = null;
                        if (m_HostPlatformDetector.DetectPlatform() == "MacOS")
                        {
                            targetAppName = assemblyName + ".app/Contents/MacOS/" + assemblyName;
                        }
                        if (preferredDirectory != null && (File.Exists(Path.Combine(preferredDirectory.FullName, targetName)) || (targetAppName != null && File.Exists(Path.Combine(preferredDirectory.FullName, targetAppName)))))
                        {
                            if (targetAppName != null && File.Exists(Path.Combine(preferredDirectory.FullName, targetAppName)))
                            {
                                // We must use the 'defaults' tool on macOS to determine if the target is a
                                // graphical application.  We do this by checking for the presence of NSPrincipalClass
                                // in the Info.plist file, which must be present for graphical applications to
                                // work.  If it does not exist, we assume it is a command-line application and run
                                // it normally like on any other platform.  We have to do this because the native
                                // entry point is the only one that has access to the GUI, while the non-native
                                // entry point is the only one that has the correct working directory set on
                                // startup.
                                if (_graphicalAppDetection.TargetMacOSAppIsGraphical(Path.Combine(preferredDirectory.FullName, assemblyName + ".app")))
                                {
                                    executablePath     = Path.Combine(preferredDirectory.FullName, targetAppName);
                                    executableIsNative = true;
                                }
                            }
                            if (executablePath == null && File.Exists(Path.Combine(preferredDirectory.FullName, targetName)))
                            {
                                executablePath = Path.Combine(preferredDirectory.FullName, targetName);
                            }
                        }
                        else
                        {
                            foreach (var subdirectory in subdirectories)
                            {
                                var    tempPath    = Path.Combine(subdirectory.FullName, assemblyName + ".exe");
                                string tempAppName = null;
                                if (m_HostPlatformDetector.DetectPlatform() == "MacOS")
                                {
                                    tempAppName = Path.Combine(subdirectory.FullName, assemblyName + ".app/Contents/MacOS/" + assemblyName);
                                }

                                if (tempAppName != null && File.Exists(tempAppName))
                                {
                                    // We must use the 'defaults' tool on macOS to determine if the target is a
                                    // graphical application.  We do this by checking for the presence of NSPrincipalClass
                                    // in the Info.plist file, which must be present for graphical applications to
                                    // work.  If it does not exist, we assume it is a command-line application and run
                                    // it normally like on any other platform.  We have to do this because the native
                                    // entry point is the only one that has access to the GUI, while the non-native
                                    // entry point is the only one that has the correct working directory set on
                                    // startup.
                                    if (_graphicalAppDetection.TargetMacOSAppIsGraphical(Path.Combine(subdirectory.FullName, assemblyName + ".app")))
                                    {
                                        executablePath     = tempAppName;
                                        executableIsNative = true;
                                        break;
                                    }
                                }
                                if (File.Exists(tempPath))
                                {
                                    executablePath = tempPath;
                                    break;
                                }
                            }
                        }
                    }
                    else if (document.Root.Name.LocalName == "ExternalProject")
                    {
                        foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                        {
                            var name = node.Attribute(XName.Get("Name")).Value;
                            var path = node.Attribute(XName.Get("Path")).Value;

                            if (name == execution.ExecuteProjectName)
                            {
                                executablePath = Path.Combine(target.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                break;
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            RedirectableConsole.WriteLine(
                                "There is no output path for '" + execution.ExecuteProjectName + "'; has the project been built?");
                            return(1);
                        }
                        else
                        {
                            executablePath     = globalToolPath;
                            executableIsNative = m_HostPlatformDetector.DetectPlatform() == "MacOS" && globalToolPath.EndsWith(".app");
                        }
                    }
                }
            }

            if (!(File.Exists(executablePath) || (executablePath.EndsWith(".app") && Directory.Exists(executablePath))))
            {
                RedirectableConsole.WriteLine(
                    "There is no executable for '" + execution.ExecuteProjectName + "'; has the project been built?");
                return(1);
            }

            var arguments = string.Empty;

            if (execution.ExecuteProjectArguments.Length > 0)
            {
                arguments = execution.ExecuteProjectArguments
                            .Select(x => "\"" + x.Replace("\"", "\\\"") + "\"")
                            .Aggregate((a, b) => a + " " + b);
            }

            ProcessStartInfo startInfo;

            if (Path.DirectorySeparatorChar == '/' && !executableIsNative)
            {
                var mono = "mono";
                if (m_HostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/mono"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find Mono with the which tool, manually set the
                    // path here in an attempt to find it.
                    mono = "/usr/local/bin/mono";
                }

                startInfo = new ProcessStartInfo(
                    mono,
                    "--debug \"" + executablePath + "\" " + arguments);
            }
            else
            {
                if (m_HostPlatformDetector.DetectPlatform() == "MacOS" && executablePath.EndsWith(".app"))
                {
                    // We must use 'open -a' to launch this application.
                    arguments      = "-a '" + executablePath.Replace("'", "'\"'\"'") + "' " + arguments;
                    executablePath = "/usr/bin/open";
                }

                startInfo = new ProcessStartInfo(
                    executablePath,
                    arguments);
            }
            startInfo.UseShellExecute = false;

            var process = Process.Start(startInfo);

            process.WaitForExit();
            return(process.ExitCode);
        }
예제 #12
0
        public int Execute(Execution execution)
        {
            var assemblyPath = Assembly.GetEntryAssembly().Location;
            var fileInfo     = new FileInfo(assemblyPath);
            var modulePath   = fileInfo.DirectoryName;

            if (modulePath == null)
            {
                Console.WriteLine(
                    "Unable to determine the location of Protobuild.");
                return(1);
            }

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                modulePath = _workingDirectoryProvider.GetPath();
            }

            string executablePath = null;

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                // We can only run global tools.
                var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                if (globalToolPath == null)
                {
                    Console.WriteLine(
                        "There is no global tool registered as '" + execution.ExecuteProjectName + "'");
                    return(1);
                }
                else
                {
                    executablePath = globalToolPath;
                }
            }
            else
            {
                var platform    = this.m_HostPlatformDetector.DetectPlatform();
                var module      = ModuleInfo.Load(Path.Combine(modulePath, "Build", "Module.xml"));
                var definitions = module.GetDefinitionsRecursively(platform).ToList();
                var target      = definitions.FirstOrDefault(x => x.Name == execution.ExecuteProjectName);
                if (target == null)
                {
                    // Check to see if there is any external project definition that provides the tool.
                    foreach (var definition in definitions)
                    {
                        var document = XDocument.Load(definition.DefinitionPath);
                        if (document.Root.Name.LocalName == "ExternalProject")
                        {
                            foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                            {
                                var name = node.Attribute(XName.Get("Name")).Value;
                                var path = node.Attribute(XName.Get("Path")).Value;

                                if (name == execution.ExecuteProjectName)
                                {
                                    executablePath = Path.Combine(definition.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                    break;
                                }
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            Console.WriteLine(
                                "There is no project definition with name '" + execution.ExecuteProjectName + "'");
                            return(1);
                        }
                        else
                        {
                            executablePath = globalToolPath;
                        }
                    }
                }
                else
                {
                    var document = XDocument.Load(target.DefinitionPath);
                    if (document.Root.Name.LocalName == "Project")
                    {
                        var assemblyName       = this.m_ProjectOutputPathCalculator.GetProjectAssemblyName(platform, target, document);
                        var prefixPath         = this.m_ProjectOutputPathCalculator.GetProjectOutputPathPrefix(platform, target, document, false);
                        var directory          = new DirectoryInfo(Path.Combine(modulePath, prefixPath));
                        var subdirectories     = directory.GetDirectories();
                        var preferredName      = (execution.ExecuteProjectConfiguration ?? "Debug").ToLowerInvariant();
                        var preferredDirectory = subdirectories.FirstOrDefault(x => x.Name.ToLowerInvariant() == preferredName);
                        if (preferredDirectory != null && File.Exists(Path.Combine(preferredDirectory.FullName, assemblyName + ".exe")))
                        {
                            executablePath = Path.Combine(preferredDirectory.FullName, assemblyName + ".exe");
                        }
                        else
                        {
                            string tempPath = null;
                            foreach (var subdirectory in subdirectories)
                            {
                                tempPath = Path.Combine(subdirectory.FullName, assemblyName + ".exe");
                                if (File.Exists(tempPath))
                                {
                                    break;
                                }
                            }
                            if (tempPath != null && File.Exists(tempPath))
                            {
                                executablePath = tempPath;
                            }
                        }
                    }
                    else if (document.Root.Name.LocalName == "ExternalProject")
                    {
                        foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                        {
                            var name = node.Attribute(XName.Get("Name")).Value;
                            var path = node.Attribute(XName.Get("Path")).Value;

                            if (name == execution.ExecuteProjectName)
                            {
                                executablePath = Path.Combine(target.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                break;
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            Console.WriteLine(
                                "There is no output path for '" + execution.ExecuteProjectName + "'; has the project been built?");
                            return(1);
                        }
                        else
                        {
                            executablePath = globalToolPath;
                        }
                    }
                }
            }

            if (!File.Exists(executablePath))
            {
                Console.WriteLine(
                    "There is no executable for '" + execution.ExecuteProjectName + "'; has the project been built?");
                return(1);
            }

            var arguments = string.Empty;

            if (execution.ExecuteProjectArguments.Length > 0)
            {
                arguments = execution.ExecuteProjectArguments
                            .Select(x => "\"" + x.Replace("\"", "\\\"") + "\"")
                            .Aggregate((a, b) => a + " " + b);
            }

            ProcessStartInfo startInfo;

            if (Path.DirectorySeparatorChar == '/')
            {
                var mono = "mono";
                if (m_HostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/mono"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find Mono with the which tool, manually set the
                    // path here in an attempt to find it.
                    mono = "/usr/local/bin/mono";
                }

                startInfo = new ProcessStartInfo(
                    mono,
                    "--debug \"" + executablePath + "\" " + arguments);
            }
            else
            {
                startInfo = new ProcessStartInfo(
                    executablePath,
                    arguments);
            }
            startInfo.UseShellExecute = false;

            var process = Process.Start(startInfo);

            process.WaitForExit();
            return(process.ExitCode);
        }
예제 #13
0
        public int Execute(Execution execution)
        {
            var    hostPlatform          = _hostPlatformDetector.DetectPlatform();
            string builderPathNativeArch = null;
            string builderPath64         = null;
            string builderPath32         = null;
            var    extraArgsNativeArch   = string.Empty;
            var    extraArgs64           = string.Empty;
            var    extraArgs32           = string.Empty;
            var    extraArgsGeneral      = string.Empty;

            if (hostPlatform == "Windows")
            {
                foreach (var arch in new[] { RegistryView.Default, RegistryView.Registry32, RegistryView.Registry64 })
                {
                    // Find latest version of MSBuild.
                    var registryKey =
                        RegistryKey.OpenBaseKey(
                            RegistryHive.LocalMachine,
                            arch)
                        .OpenSubKey("SOFTWARE")?
                        .OpenSubKey("Microsoft")?
                        .OpenSubKey("MSBuild")?
                        .OpenSubKey("ToolsVersions");
                    if (registryKey == null)
                    {
                        if (arch == RegistryView.Registry64)
                        {
                            continue;
                        }

                        Console.Error.WriteLine(
                            "ERROR: No versions of MSBuild were available " +
                            "according to the registry (or they were not readable).");
                        return(1);
                    }

                    var subkeys         = registryKey.GetSubKeyNames();
                    var orderedVersions =
                        subkeys.OrderByDescending(x => int.Parse(x.Split('.').First(), CultureInfo.InvariantCulture));
                    var builderPath = (from version in orderedVersions
                                       let path = (string)registryKey.OpenSubKey(version)?.GetValue("MSBuildToolsPath")
                                                  where path != null && Directory.Exists(path)
                                                  let msbuild = Path.Combine(path, "MSBuild.exe")
                                                                where File.Exists(msbuild)
                                                                select msbuild).FirstOrDefault();

                    if (builderPath == null)
                    {
                        if (arch == RegistryView.Registry64)
                        {
                            continue;
                        }

                        Console.Error.WriteLine(
                            "ERROR: Unable to find installed MSBuild in any installed tools version.");
                        return(1);
                    }

                    var extraArgs = string.Empty;
                    if (!builderPath.Contains("v2.0.50727"))
                    {
                        extraArgs = "/m ";
                    }

                    switch (arch)
                    {
                    case RegistryView.Default:
                        builderPathNativeArch = builderPath;
                        extraArgsNativeArch   = extraArgs;
                        break;

                    case RegistryView.Registry32:
                        builderPath32 = builderPath;
                        extraArgs32   = extraArgs;
                        break;

                    case RegistryView.Registry64:
                        builderPath64 = builderPath;
                        extraArgs64   = extraArgs;
                        break;
                    }
                }
            }
            else
            {
                // Find path to xbuild.
                var whichPaths = new[] { "/bin/which", "/usr/bin/which" };
                foreach (var w in whichPaths)
                {
                    if (File.Exists(w))
                    {
                        var whichProcess = Process.Start(new ProcessStartInfo(w, "xbuild")
                        {
                            RedirectStandardOutput = true,
                            UseShellExecute        = false
                        });
                        if (whichProcess == null)
                        {
                            continue;
                        }
                        var result = whichProcess.StandardOutput.ReadToEnd().Trim();
                        if (!string.IsNullOrWhiteSpace(result) && File.Exists(result))
                        {
                            builderPathNativeArch = result;
                            break;
                        }
                    }
                }

                if (builderPathNativeArch == null && _hostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/xbuild"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find xbuild with the which tool, manually set the
                    // path here in an attempt to find it.
                    builderPathNativeArch = "/usr/local/bin/xbuild";
                }

                if (builderPathNativeArch == null)
                {
                    Console.Error.WriteLine("ERROR: Unable to find xbuild on the current PATH.");
                    return(1);
                }

                builderPath32 = builderPathNativeArch;
                builderPath64 = builderPathNativeArch;
            }

            if (!string.IsNullOrWhiteSpace(execution.BuildTarget))
            {
                extraArgsGeneral += "/t:\"" + execution.BuildTarget + "\" ";
            }
            foreach (var prop in execution.BuildProperties)
            {
                extraArgsGeneral += "/p:\"" + prop.Key.Replace("\"", "\\\"") + "\"=\"" + (prop.Value ?? string.Empty).Replace("\"", "\\\"") + "\" ";
            }

            switch (execution.BuildProcessArchitecture)
            {
            case "x86":
                Console.WriteLine("INFO: Using " + builderPath32 + " (forced 32-bit) to perform this build.");
                break;

            case "x64":
                Console.WriteLine("INFO: Using " + builderPath64 + " (forced 64-bit) to perform this build.");
                break;

            case "Default":
            default:
                Console.WriteLine("INFO: Using " + builderPathNativeArch + " (32-bit: " + builderPath32 + ") to perform this build.");
                break;
            }

            var targetPlatforms = (execution.Platform ?? hostPlatform).Split(',');
            var module          = ModuleInfo.Load(Path.Combine("Build", "Module.xml"));

            foreach (var platform in targetPlatforms)
            {
                string builderPath;
                string extraArgs;

                switch (execution.BuildProcessArchitecture)
                {
                case "x86":
                    builderPath = builderPath32;
                    extraArgs   = extraArgs32 + extraArgsGeneral;
                    break;

                case "x64":
                    builderPath = builderPath64;
                    extraArgs   = extraArgs64 + extraArgsGeneral;
                    break;

                case "Default":
                default:
                    builderPath = platform == "WindowsPhone" ? builderPath32 : builderPathNativeArch;
                    extraArgs   = (platform == "WindowsPhone" ? extraArgs32 : extraArgsNativeArch) + extraArgsGeneral;
                    break;
                }

                var fileToBuild = module.Name + "." + platform + ".sln";

                Console.WriteLine("INFO: Executing " + builderPath + " with arguments: " + extraArgs + fileToBuild);

                var process =
                    Process.Start(new ProcessStartInfo(builderPath, extraArgs + fileToBuild)
                {
                    UseShellExecute = false
                });
                if (process == null)
                {
                    Console.Error.WriteLine("ERROR: Build process did not start successfully.");
                    return(1);
                }
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            return(0);
        }
        public override bool Execute()
        {
            if (string.Compare(Platform, "Web", StringComparison.InvariantCultureIgnoreCase) == 0)
            {
                // Trigger JSIL provider download if needed.
                string jsilDirectory, jsilCompilerFile;
                if (!m_JSILProvider.GetJSIL(out jsilDirectory, out jsilCompilerFile))
                {
                    return(false);
                }
            }

            var module = ModuleInfo.Load(Path.Combine(RootPath, "Build", "Module.xml"));

            LogMessage(
                "Starting generation of projects for " + Platform);

            var definitions    = module.GetDefinitionsRecursively(Platform).ToArray();
            var loadedProjects = new List <LoadedDefinitionInfo>();

            if (_hostPlatformDetector.DetectPlatform() == "Windows")
            {
                var concurrentProjects = new ConcurrentBag <LoadedDefinitionInfo>();

                Parallel.ForEach(definitions, definition =>
                {
                    LogMessage("Loading: " + definition.Name);
                    concurrentProjects.Add(
                        m_ProjectLoader.Load(
                            Platform,
                            module,
                            definition));
                });

                // Do this so we maintain order with the original definitions list.
                foreach (var definition in definitions)
                {
                    var loadedProject = concurrentProjects.FirstOrDefault(x => x.Definition == definition);
                    if (loadedProject != null)
                    {
                        loadedProjects.Add(loadedProject);
                    }
                }
            }
            else
            {
                foreach (var definition in definitions)
                {
                    LogMessage("Loading: " + definition.Name);
                    loadedProjects.Add(
                        m_ProjectLoader.Load(
                            Platform,
                            module,
                            definition));
                }
            }

            var                  serviceManager = new ServiceManager(Platform);
            List <Service>       services;
            TemporaryServiceSpec serviceSpecPath;

            if (ServiceSpecPath == null)
            {
                serviceManager.SetRootDefinitions(module.GetDefinitions());

                if (EnableServices == null)
                {
                    EnableServices = new string[0];
                }

                if (DisableServices == null)
                {
                    DisableServices = new string[0];
                }

                foreach (var service in EnableServices)
                {
                    serviceManager.EnableService(service);
                }

                foreach (var service in DisableServices)
                {
                    serviceManager.DisableService(service);
                }

                if (DebugServiceResolution)
                {
                    serviceManager.EnableDebugInformation();
                }

                try
                {
                    services = serviceManager.CalculateDependencyGraph(loadedProjects.Select(x => x.Project).ToList());
                }
                catch (InvalidOperationException ex)
                {
                    RedirectableConsole.WriteLine("Error during service resolution: " + ex.Message);
                    return(false);
                }

                serviceSpecPath = serviceManager.SaveServiceSpec(services);

                foreach (var service in services)
                {
                    if (service.ServiceName != null)
                    {
                        LogMessage("Enabled service: " + service.FullName);
                    }
                }
            }
            else
            {
                services        = serviceManager.LoadServiceSpec(ServiceSpecPath);
                serviceSpecPath = new TemporaryServiceSpec(ServiceSpecPath, true);
            }

            using (serviceSpecPath)
            {
                var submodulesToProcess = new List <ModuleInfo>();
                var allSubmodules       = module.GetSubmodules(Platform);

                if (_hostPlatformDetector.DetectPlatform() == "Windows")
                {
                    var concurrentSubmodulesToProcess = new ConcurrentBag <ModuleInfo>();

                    Parallel.ForEach(allSubmodules, submodule =>
                    {
                        if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule,
                                                                        Feature.OptimizationSkipInvocationOnNoStandardProjects))
                        {
                            if (submodule.GetDefinitionsRecursively(Platform).All(x => !x.IsStandardProject))
                            {
                                // Do not invoke this submodule.
                                LogMessage(
                                    "Skipping submodule generation for " + submodule.Name +
                                    " (there are no projects to generate)");
                            }
                            else
                            {
                                concurrentSubmodulesToProcess.Add(submodule);
                            }
                        }
                    });

                    // Do this so we maintain order with the original GetSubmodules list.
                    foreach (var submodule in allSubmodules)
                    {
                        if (concurrentSubmodulesToProcess.Contains(submodule))
                        {
                            submodulesToProcess.Add(submodule);
                        }
                    }
                }
                else
                {
                    foreach (var submodule in module.GetSubmodules(Platform))
                    {
                        if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule,
                                                                        Feature.OptimizationSkipInvocationOnNoStandardProjects))
                        {
                            if (submodule.GetDefinitionsRecursively(Platform).All(x => !x.IsStandardProject))
                            {
                                // Do not invoke this submodule.
                                LogMessage(
                                    "Skipping submodule generation for " + submodule.Name +
                                    " (there are no projects to generate)");
                            }
                            else
                            {
                                submodulesToProcess.Add(submodule);
                            }
                        }
                    }
                }

                // Run Protobuild in batch mode in each of the submodules
                // where it is present.
                foreach (var submodule in submodulesToProcess)
                {
                    LogMessage(
                        "Invoking submodule generation for " + submodule.Name);
                    var noResolve = _featureManager.IsFeatureEnabledInSubmodule(module, submodule,
                                                                                Feature.PackageManagementNoResolve)
                        ? " -no-resolve"
                        : string.Empty;
                    var noHostPlatform = DisableHostPlatformGeneration &&
                                         _featureManager.IsFeatureEnabledInSubmodule(module, submodule,
                                                                                     Feature.NoHostGenerate)
                        ? " -no-host-generate"
                        : string.Empty;
                    _moduleExecution.RunProtobuild(
                        submodule,
                        _featureManager.GetFeatureArgumentToPassToSubmodule(module, submodule) +
                        "-generate " + Platform +
                        " -spec " + serviceSpecPath +
                        " " + m_PackageRedirector.GetRedirectionArguments() +
                        noResolve + noHostPlatform);
                    LogMessage(
                        "Finished submodule generation for " + submodule.Name);
                }

                var repositoryPaths = new List <string>();

                if (_hostPlatformDetector.DetectPlatform() == "Windows")
                {
                    var concurrentRepositoryPaths = new ConcurrentBag <string>();

                    Parallel.ForEach(definitions.Where(x => x.ModulePath == module.Path), definition =>
                    {
                        if (definition.PostBuildHook && RequiresHostPlatform != null)
                        {
                            // We require the host platform projects at this point.
                            RequiresHostPlatform();
                        }

                        string repositoryPath;
                        var definitionCopy = definition;
                        m_ProjectGenerator.Generate(
                            definition,
                            loadedProjects,
                            WorkingDirectory,
                            RootPath,
                            definition.Name,
                            Platform,
                            services,
                            out repositoryPath,
                            () => LogMessage("Generating: " + definitionCopy.Name),
                            DebugProjectGeneration);

                        // Only add repository paths if they should be generated.
                        if (module.GenerateNuGetRepositories && !string.IsNullOrEmpty(repositoryPath))
                        {
                            concurrentRepositoryPaths.Add(repositoryPath);
                        }
                    });

                    repositoryPaths = concurrentRepositoryPaths.ToList();
                }
                else
                {
                    foreach (var definition in definitions.Where(x => x.ModulePath == module.Path))
                    {
                        if (definition.PostBuildHook && RequiresHostPlatform != null)
                        {
                            // We require the host platform projects at this point.
                            RequiresHostPlatform();
                        }

                        string repositoryPath;
                        var    definitionCopy = definition;
                        m_ProjectGenerator.Generate(
                            definition,
                            loadedProjects,
                            WorkingDirectory,
                            RootPath,
                            definition.Name,
                            Platform,
                            services,
                            out repositoryPath,
                            () => LogMessage("Generating: " + definitionCopy.Name),
                            DebugProjectGeneration);

                        // Only add repository paths if they should be generated.
                        if (module.GenerateNuGetRepositories && !string.IsNullOrEmpty(repositoryPath))
                        {
                            repositoryPaths.Add(repositoryPath);
                        }
                    }
                }

                var solution = Path.Combine(
                    RootPath,
                    ModuleName + "." + Platform + ".sln");
                LogMessage("Generating: (solution)");
                m_SolutionGenerator.Generate(
                    WorkingDirectory,
                    module,
                    loadedProjects.Select(x => x.Project).ToList(),
                    Platform,
                    solution,
                    services,
                    repositoryPaths,
                    DebugProjectGeneration);

                // Only save the specification cache if we allow synchronisation
                if (module.DisableSynchronisation == null || !module.DisableSynchronisation.Value)
                {
                    var serviceCache = Path.Combine(RootPath, ModuleName + "." + Platform + ".speccache");
                    LogMessage("Saving service specification");
                    File.Copy(serviceSpecPath.Path, serviceCache, true);
                }

                LogMessage(
                    "Generation complete.");
            }

            return(true);
        }
예제 #15
0
        public IPackageMetadata ResolveSource(string workingDirectory, PackageRequestRef request)
        {
            var components = request.Uri.Split(new[] { '|' }, 2);

            var repository  = NormalizeScheme(components[0]);
            var packageName = components[1];
            var version     = request.GitRef;

            var semVerRegex  = new Regex("^[0-9]\\.[0-9]\\.[0-9](\\-.*)?$");
            var gitHashRegex = new Regex("^[0-9a-fA-F]{40}$");

            var shouldQuerySourceRepository = false;

            if (semVerRegex.IsMatch(version))
            {
                // This is a semantic version; leave as-is.
            }
            else if (gitHashRegex.IsMatch(version))
            {
                // This is a Git hash, convert it to NuGet's semantic version.
                version = NuGetVersionHelper.CreateNuGetPackageVersion(version, request.Platform);
            }
            else
            {
                // This is a branch, or other kind of source reference.  We need
                // to query the source repository to resolve it to a Git hash.
                shouldQuerySourceRepository = true;
            }

            string serviceJson;
            var    serviceIndex = _packageRequestCache.TryGetOptionallyCachedJsonObject(
                repository,
                !request.ForceUpgrade,
                out serviceJson,
                id => GetData(new Uri(id)));

            string registrationsBaseUrl = null;

            foreach (var entry in serviceIndex.resources)
            {
                var entryType = (string)entry["@type"];
                if (entryType == "RegistrationsBaseUrl")
                {
                    registrationsBaseUrl = (string)entry["@id"];
                }
            }

            if (registrationsBaseUrl == null)
            {
                throw new InvalidOperationException("Unable to locate RegistrationsBaseUrl service.");
            }

            var packageMetadataUrl =
                $"{registrationsBaseUrl.TrimEnd(new[] {'/'})}/{packageName.ToLowerInvariant()}/index.json";

            string packageMetadataJson;
            var    packageMetadata = _packageRequestCache.TryGetOptionallyCachedJsonObject(
                packageMetadataUrl,
                !request.ForceUpgrade && request.IsStaticReference,
                out packageMetadataJson,
                id => GetData(new Uri(id)));

            string latestPackageVersion = null;

            foreach (var item in packageMetadata.items)
            {
                if (latestPackageVersion == null || string.CompareOrdinal((string)item.upper, latestPackageVersion) > 0)
                {
                    latestPackageVersion = item.upper;
                }
            }

            var packagesByVersionLock = new object();
            var packagesByVersion     = new Dictionary <string, dynamic>();

            if (_hostPlatformDetector.DetectPlatform() == "Windows")
            {
                // Do this in parallel as we may need to make multiple HTTPS requests.
                Parallel.ForEach((IEnumerable <object>)packageMetadata.items,
                                 item => PopulatePackagesByVersion(packagesByVersionLock, packagesByVersion, (dynamic)item, request));
            }
            else
            {
                // Parallelisation is not safe on this platform, do it sequentually.
                foreach (var item in packageMetadata.items)
                {
                    PopulatePackagesByVersion(packagesByVersionLock, packagesByVersion, item, request);
                }
            }

            string packageType = PackageManager.PACKAGE_TYPE_LIBRARY;

            string sourceCodeUrl = null;
            string commitHashForSourceResolve = null;

            if (shouldQuerySourceRepository)
            {
                var lookupVersion = latestPackageVersion;
                if (!packagesByVersion.ContainsKey(lookupVersion) && packagesByVersion.ContainsKey(lookupVersion + "+git.unspecified"))
                {
                    lookupVersion += "+git.unspecified";
                }
                sourceCodeUrl = ExtractSourceRepository(packagesByVersion[lookupVersion]);
                packageType   = ExtractPackageType(packagesByVersion[lookupVersion]);

                if (!string.IsNullOrWhiteSpace(sourceCodeUrl))
                {
                    if (sourceCodeUrl.StartsWith("git="))
                    {
                        sourceCodeUrl = sourceCodeUrl.Substring("git=".Length);

                        var performGitLsRemote = true;
                        if (sourceCodeUrl.StartsWith("https://github.com/"))
                        {
                            try
                            {
                                // This is a GitHub repository.  During the installation of Protobuild Manager (hosted on GitHub), we need
                                // to resolve the latest version on NuGet, but we can't do this because Git may not be in the PATH or may
                                // not be available.  We still want developers to be able to install Protobuild Manager without Git on
                                // their PATH (as they may have dedicated shells to use it), so we attempt to use the GitHub API to resolve
                                // the commit hash first.
                                string gitHubJsonInfo;
                                var    gitHubComponents =
                                    sourceCodeUrl.Substring("https://github.com/".Length).Split('/');
                                var gitHubOwner  = gitHubComponents[0];
                                var gitHubRepo   = gitHubComponents[1];
                                var gitHubApiUrl = "https://api.github.com/repos/" + gitHubOwner +
                                                   "/" +
                                                   gitHubRepo + "/branches/" + version;
                                var gitHubJson = _packageRequestCache.TryGetOptionallyCachedJsonObject(
                                    gitHubApiUrl,
                                    !request.ForceUpgrade && request.IsStaticReference,
                                    out packageMetadataJson,
                                    id =>
                                {
                                    using (var client = new RetryableWebClient())
                                    {
                                        client.SilentOnError = true;
                                        client.SetHeader("User-Agent", "Protobuild NuGet Lookup/v1.0");
                                        client.SetHeader("Accept", "application/vnd.github.v3+json");

                                        return(client.DownloadString(gitHubApiUrl));
                                    }
                                });
                                var commitHash = gitHubJson.commit.sha;

                                if (!string.IsNullOrWhiteSpace(commitHash))
                                {
                                    // This is a match and we've found our Git hash to use.
                                    version =
                                        NuGetVersionHelper.CreateNuGetPackageVersion(commitHash.Trim(),
                                                                                     request.Platform);
                                    commitHashForSourceResolve = commitHash.Trim();
                                    performGitLsRemote         = false;
                                }
                            }
                            catch (Exception)
                            {
                                Console.WriteLine("NOTICE: Unable to lookup version information via GitHub API; falling back to 'git ls-remote'");
                            }
                        }

                        if (performGitLsRemote)
                        {
                            var heads = _packageRequestCache.TryGetOptionallyCachedData(
                                "git:" + sourceCodeUrl,
                                !request.ForceUpgrade && request.IsStaticReference,
                                id => GitUtils.RunGitAndCapture(
                                    workingDirectory,
                                    null,
                                    "ls-remote --heads " + new Uri(sourceCodeUrl)));

                            var lines = heads.Split(new string[] { "\r\n", "\n", "\r" },
                                                    StringSplitOptions.RemoveEmptyEntries);

                            foreach (var line in lines)
                            {
                                var sourceEntryComponents = line.Split('\t');
                                if (sourceEntryComponents.Length >= 2)
                                {
                                    var branchName = sourceEntryComponents[1].Trim();

                                    if (branchName.StartsWith("refs/heads/"))
                                    {
                                        branchName = branchName.Substring("refs/heads/".Length);
                                    }
                                    else
                                    {
                                        continue;
                                    }

                                    if (string.Equals(version, branchName, StringComparison.InvariantCulture))
                                    {
                                        // This is a match and we've found our Git hash to use.
                                        version =
                                            NuGetVersionHelper.CreateNuGetPackageVersion(
                                                sourceEntryComponents[0].Trim(),
                                                request.Platform);
                                        commitHashForSourceResolve = sourceEntryComponents[0].Trim();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Unknown source code repository type '" + sourceCodeUrl + "'");
                    }

                    // If we fall out of this loop, we'll hit the next if statement and most likely fail.
                }
            }

            string binaryUri    = null;
            string binaryFormat = null;

            if (!packagesByVersion.ContainsKey(version))
            {
                if (string.IsNullOrWhiteSpace(sourceCodeUrl))
                {
                    throw new InvalidOperationException(
                              "Unable to resolve binary package for version \"" +
                              version + "\" and platform \"" + request.Platform +
                              "\" and this package does not have a source repository");
                }
                else
                {
                    RedirectableConsole.WriteLine("Unable to resolve binary package for version \"" + version +
                                                  "\" and platform \"" + request.Platform + "\", falling back to source version");
                }
            }
            else
            {
                sourceCodeUrl = ExtractSourceRepository(packagesByVersion[version]);
                packageType   = ExtractPackageType(packagesByVersion[version]);

                if (!string.IsNullOrWhiteSpace(sourceCodeUrl))
                {
                    if (sourceCodeUrl.StartsWith("git="))
                    {
                        sourceCodeUrl = sourceCodeUrl.Substring("git=".Length);
                    }
                    else
                    {
                        throw new InvalidOperationException("Unknown source code repository type '" + sourceCodeUrl + "'");
                    }
                }

                if (commitHashForSourceResolve == null)
                {
                    commitHashForSourceResolve = ExtractCommitHash(packagesByVersion[version]);
                }

                // packageContent may not be under catalogEntry; our best guess is that NuGet
                // moved it from the root to catalogEntry at some point in the past, but not
                // all of the registrations are updated with it under catalogEntry, e.g. RestSharp
                try
                {
                    binaryUri = packagesByVersion[version].catalogEntry.packageContent;
                }
                catch
                {
                    binaryUri = packagesByVersion[version].packageContent;
                }

                binaryFormat = PackageManager.ARCHIVE_FORMAT_NUGET_ZIP;
            }

            return(new NuGet3PackageMetadata(
                       repository,
                       packageName,
                       packageType,
                       sourceCodeUrl,
                       request.Platform,
                       version,
                       binaryFormat,
                       binaryUri,
                       commitHashForSourceResolve,
                       (workingDirectoryAlt, metadata, folder, name, upgrade, source) =>
            {
                if (source == true)
                {
                    _sourcePackageResolve.Resolve(workingDirectoryAlt, metadata, folder, name, upgrade);
                }
                else
                {
                    _binaryPackageResolve.Resolve(workingDirectoryAlt, metadata, folder, name, upgrade);
                }
            }));
        }