private void AutomaticallyPackageExternalProject( DefinitionInfo[] definitions, List <Service> services, FileFilter fileFilter, string rootPath, string platform, DefinitionInfo definition, List <string> temporaryFiles) { var document = new XmlDocument(); document.Load(definition.DefinitionPath); var externalProjectDocument = new XmlDocument(); externalProjectDocument.AppendChild(externalProjectDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); var externalProject = externalProjectDocument.CreateElement("ExternalProject"); externalProjectDocument.AppendChild(externalProject); externalProject.SetAttribute("Name", definition.Name); // Translate all of the references (this is a seperate method so we can call it // again when traversing into Platform nodes). this.TranslateExternalProject( definition, services, fileFilter, rootPath, platform, document.DocumentElement, externalProject, false); // Write out the external project to a temporary file and include it. var name = Path.GetRandomFileName() + "_" + definition.Name + ".xml"; var temp = Path.Combine(Path.GetTempPath(), name); temporaryFiles.Add(temp); using (var writer = XmlWriter.Create(temp, new XmlWriterSettings { Indent = true, IndentChars = " " })) { externalProjectDocument.WriteTo(writer); } fileFilter.AddManualMapping(temp, "Build/Projects/" + definition.Name + ".definition"); }
private void AutomaticallyPackageNormalProject( DefinitionInfo[] definitions, List <Service> services, FileFilter fileFilter, string rootPath, string platform, DefinitionInfo definition) { var document = XDocument.Load(definition.DefinitionPath); var platformSpecificOutputFolderElement = document.XPathSelectElement("/Project/Properties/PlatformSpecificOutputFolder"); var projectSpecificOutputFolderElement = document.XPathSelectElement("/Project/Properties/ProjectSpecificOutputFolder"); var assemblyNameForPlatformElement = document.XPathSelectElement("/Project/Properties/AssemblyName/Platform[@Name=\"" + platform + "\"]"); var assemblyNameGlobalElement = document.XPathSelectElement("/Project/Properties/Property[@Name=\"AssemblyName\"]"); var platformSpecificOutputFolder = true; var projectSpecificOutputFolder = false; if (platformSpecificOutputFolderElement != null) { platformSpecificOutputFolder = platformSpecificOutputFolderElement.Value.ToLowerInvariant() != "false"; } if (projectSpecificOutputFolderElement != null) { projectSpecificOutputFolder = projectSpecificOutputFolderElement.Value.ToLowerInvariant() == "true"; } string assemblyName = null; if (assemblyNameForPlatformElement != null) { assemblyName = assemblyNameForPlatformElement.Value; } else if (assemblyNameGlobalElement != null) { assemblyName = assemblyNameGlobalElement.Value; } else { assemblyName = definition.Name; } var assemblyFilesToCopy = new[] { assemblyName + ".exe", assemblyName + ".dll", assemblyName + ".dll.config", assemblyName + ".dll.mdb", assemblyName + ".pdb", assemblyName + ".xml", }; var outputMode = OutputPathMode.BinConfiguration; if (projectSpecificOutputFolder) { outputMode = OutputPathMode.BinProjectPlatformArchConfiguration; } if (platformSpecificOutputFolder) { outputMode = OutputPathMode.BinPlatformArchConfiguration; } var externalProjectDocument = new XmlDocument(); externalProjectDocument.AppendChild(externalProjectDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); var externalProject = externalProjectDocument.CreateElement("ExternalProject"); externalProjectDocument.AppendChild(externalProject); externalProject.SetAttribute("Name", definition.Name); // Copy the assembly itself out to the package. switch (outputMode) { case OutputPathMode.BinConfiguration: { // In this configuration, we only ship the binaries for // the default architecture (because that's all we know // about). We also have to assume the binary folder // contains binaries for the desired platform. var pathPrefix = definition.Path.Replace('\\', '/').Replace(".", "\\.") + "/bin/([^/]+)/"; if (definition.Type == "Library") { // For libraries, we only copy the assembly (and immediately related files) // into it's directory. Native binaries will be expressed through the ExternalProject. foreach (var assemblyFile in assemblyFilesToCopy) { var includeMatch = fileFilter.ApplyInclude("^" + pathPrefix + Regex.Escape(assemblyFile) + "$"); var rewriteMatch = fileFilter.ApplyRewrite("^" + pathPrefix + Regex.Escape(assemblyFile) + "$", definition.Name + "/AnyCPU/" + assemblyFile); if (includeMatch && rewriteMatch) { if (assemblyFile.EndsWith(".dll")) { var binaryEntry = externalProjectDocument.CreateElement("Binary"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\AnyCPU\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } else if (assemblyFile.EndsWith(".dll.config")) { var configEntry = externalProjectDocument.CreateElement("NativeBinary"); configEntry.SetAttribute("Path", definition.Name + "\\AnyCPU\\" + assemblyFile); externalProject.AppendChild(configEntry); } } else if (includeMatch || rewriteMatch) { throw new InvalidOperationException("Automatic filter; only one rule matched."); } } } else { // For executables, we ship everything in the output directory, because we // want the executables to be able to run from the package directory. fileFilter.ApplyInclude("^" + pathPrefix + "(.+)$"); fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/AnyCPU/$2"); } break; } case OutputPathMode.BinPlatformArchConfiguration: { // In this configuration, we ship binaries for AnyCPU, iPhone or all .NET architectures // depending on whether or not the platform produces multiple architectures. On Mono, // we can't use $(Platform) within a reference's path, so we have to keep this path static // for Mono platforms. string pathArchMatch, pathArchReplace, pathArchRuntime; switch (platform.ToLowerInvariant()) { case "ios": { pathArchMatch = "iPhone"; pathArchReplace = "iPhone"; pathArchRuntime = "iPhone"; break; } case "windowsphone": { pathArchMatch = "([^/]+)"; pathArchReplace = "$1"; pathArchRuntime = "$(Platform)"; break; } default: { pathArchMatch = "AnyCPU"; pathArchReplace = "AnyCPU"; pathArchRuntime = "AnyCPU"; break; } } var pathPrefix = definition.Path.Replace('\\', '/').Replace(".", "\\.") + "/bin/" + platform + "/" + pathArchMatch + "/([^/]+)/"; if (definition.Type == "Library") { // For libraries, we only copy the assembly (and immediately related files) // into it's directory. Native binaries will be expressed through the ExternalProject. foreach (var assemblyFile in assemblyFilesToCopy) { var includeMatch = fileFilter.ApplyInclude("^" + pathPrefix + Regex.Escape(assemblyFile) + "$"); var rewriteMatch = fileFilter.ApplyRewrite("^" + pathPrefix + Regex.Escape(assemblyFile) + "$", definition.Name + "/" + pathArchReplace + "/" + assemblyFile); if (includeMatch && rewriteMatch) { if (assemblyFile.EndsWith(".dll")) { var binaryEntry = externalProjectDocument.CreateElement("Binary"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\" + pathArchRuntime + "\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } else if (assemblyFile.EndsWith(".dll.config")) { var configEntry = externalProjectDocument.CreateElement("NativeBinary"); configEntry.SetAttribute("Path", definition.Name + "\\" + pathArchRuntime + "\\" + assemblyFile); externalProject.AppendChild(configEntry); } } else if (includeMatch || rewriteMatch) { throw new InvalidOperationException("Automatic filter; only one rule matched."); } } } else { // For executables, we ship everything in the output directory, because we // want the executables to be able to run from the package directory. fileFilter.ApplyInclude("^" + pathPrefix + "(.+)$"); if (pathArchMatch == "([^/]+)") { fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/" + pathArchReplace + "/$3"); } else { fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/" + pathArchReplace + "/$2"); } } break; } case OutputPathMode.BinProjectPlatformArchConfiguration: { throw new NotSupportedException(); break; } } // Convert all of the known references into references within the external project. var definitionsByName = definitions.ToDictionary(k => k.Name, v => v); foreach (var reference in document.XPathSelectElements("/Project/References/Reference")) { var includeAttribute = reference.Attribute(XName.Get("Include")); if (includeAttribute != null) { if (definitionsByName.ContainsKey(includeAttribute.Value)) { // This reference will be converted to an external project, // so add a reference to it (in case it contains native binaries // which need to be copied out). var referenceEntry = externalProjectDocument.CreateElement("Reference"); referenceEntry.SetAttribute("Include", includeAttribute.Value); externalProject.AppendChild(referenceEntry); } } } // Copy out any files that are marked with copy-on-build flag. var detector = new PlatformAndServiceActiveDetection(); var xmlDocument = new XmlDocument(); xmlDocument.Load(definition.DefinitionPath); var servicesInput = this.m_ServiceInputGenerator.Generate(xmlDocument, definition.Name, services); var activeServicesElement = servicesInput.ChildNodes.OfType <XmlElement>().FirstOrDefault(x => x.LocalName == "ActiveServicesNames"); var activeServices = activeServicesElement.InnerText; foreach (var file in document.XPathSelectElements("/Project/Files/*")) { var copyOnBuild = file.XPathSelectElement("CopyToOutputDirectory"); if (copyOnBuild == null) { continue; } if (copyOnBuild.Value != "PreserveNewest" && copyOnBuild.Value != "Always") { continue; } var platformsElement = file.XPathSelectElement("Platforms"); var includePlatformsElement = file.XPathSelectElement("IncludePlatforms"); var excludePlatformsElement = file.XPathSelectElement("ExcludePlatforms"); var servicesElement = file.XPathSelectElement("Services"); var includeServicesElement = file.XPathSelectElement("IncludeServices"); var excludeServicesElement = file.XPathSelectElement("ExcludeServices"); var platformsString = platformsElement != null ? platformsElement.Value : string.Empty; var includePlatformsString = includePlatformsElement != null ? includePlatformsElement.Value : string.Empty; var excludePlatformsString = excludePlatformsElement != null ? excludePlatformsElement.Value : string.Empty; var servicesString = servicesElement != null ? servicesElement.Value : string.Empty; var includeServicesString = includeServicesElement != null ? includeServicesElement.Value : string.Empty; var excludeServicesString = excludeServicesElement != null ? excludeServicesElement.Value : string.Empty; if (detector.ProjectAndServiceIsActive( platformsString, includePlatformsString, excludePlatformsString, servicesString, includeServicesString, excludeServicesString, platform, activeServices)) { var include = file.Attribute(XName.Get("Include")); var linkElement = file.XPathSelectElement("Link"); var link = linkElement != null ? linkElement.Value : include.Value; var fileInfo = new FileInfo(Path.Combine( definition.ModulePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar), definition.Path.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar), include.Value.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar))); if (definition.Type == "Library") { // For libraries, we're copying the content so that applications using // the libraries will have the content. This is most often used to // ship native binaries (although NativeBinary in external projects now // supersedes this). if (link.Contains('/') || link.Contains('\\')) { Console.WriteLine( "WARNING: Copy-on-build file '" + link + "' in library project which " + "does not output to root of project detected. This is not supported."); } else { if (fileInfo.Name != link) { Console.WriteLine( "WARNING: Copy-on-build file in library project does not have the same " + "name when copied to build directory. This is not supported."); } else { var sourcePath = fileInfo.FullName; sourcePath = sourcePath.Substring(rootPath.Length).Replace('\\', '/').TrimStart('/'); var destPath = Path.Combine("_AutomaticExternals", sourcePath); var sourcePathRegex = this.ConvertPathWithMSBuildVariablesFind(sourcePath); var destPathRegex = this.ConvertPathWithMSBuildVariablesReplace(destPath.Replace('\\', '/')); var includeMatch = fileFilter.ApplyInclude(sourcePathRegex); fileFilter.ApplyRewrite(sourcePathRegex, destPathRegex); if (includeMatch) { var nativeBinaryEntry = externalProjectDocument.CreateElement("NativeBinary"); nativeBinaryEntry.SetAttribute("Path", destPath); externalProject.AppendChild(nativeBinaryEntry); } else { throw new InvalidOperationException( "File not found at " + sourcePath + " when converting " + "copy-on-build file in library project."); } } } } } } // Write out the external project to a temporary file and include it. var name = Path.GetRandomFileName() + "_" + definition.Name + ".xml"; var temp = Path.Combine(Path.GetTempPath(), name); using (var writer = XmlWriter.Create(temp, new XmlWriterSettings { Indent = true, IndentChars = " " })) { externalProjectDocument.WriteTo(writer); } fileFilter.AddManualMapping(temp, "Build/Projects/" + definition.Name + ".definition"); }
public void Autopackage( FileFilter fileFilter, Execution execution, ModuleInfo module, string rootPath, string platform) { var definitions = module.GetDefinitionsRecursively(platform).ToArray(); var loadedProjects = new List <XmlDocument>(); foreach (var definition in definitions) { Console.WriteLine("Loading: " + definition.Name); loadedProjects.Add( this.m_ProjectLoader.Load( Path.Combine( definition.ModulePath, "Build", "Projects", definition.Name + ".definition"), platform, module.Path, definition.ModulePath)); } var serviceManager = new ServiceManager(platform); List <Service> services; serviceManager.SetRootDefinitions(module.GetDefinitions()); var enabledServices = execution.EnabledServices.ToArray(); var disabledServices = execution.DisabledServices.ToArray(); foreach (var service in enabledServices) { serviceManager.EnableService(service); } foreach (var service in disabledServices) { serviceManager.DisableService(service); } services = serviceManager.CalculateDependencyGraph(loadedProjects); foreach (var service in services) { if (service.ServiceName != null) { Console.WriteLine("Enabled service: " + service.FullName); } } foreach (var definition in definitions) { if (definition.SkipAutopackage) { Console.WriteLine("Skipping: " + definition.Name); continue; } switch (definition.Type) { case "External": Console.WriteLine("Packaging: " + definition.Name); this.AutomaticallyPackageExternalProject(definitions, services, fileFilter, rootPath, platform, definition); break; case "Content": Console.WriteLine("Content project definition skipped: " + definition.Name); break; default: Console.WriteLine("Packaging: " + definition.Name); this.AutomaticallyPackageNormalProject(definitions, services, fileFilter, rootPath, platform, definition); break; } } // If there is no Module.xml in the source mappings already, then copy the current module. var filterDictionary = fileFilter.ToDictionary(k => k.Key, v => v.Value); if (!filterDictionary.ContainsValue("Build/Module.xml")) { fileFilter.AddManualMapping(Path.Combine(module.Path, "Build", "Module.xml"), "Build/Module.xml"); } }
private void AutomaticallyPackageNormalProject( DefinitionInfo[] definitions, List <Service> services, FileFilter fileFilter, string rootPath, string platform, DefinitionInfo definition, List <string> temporaryFiles) { var document = XDocument.Load(definition.DefinitionPath); var externalProjectDocument = new XmlDocument(); externalProjectDocument.AppendChild(externalProjectDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); var externalProject = externalProjectDocument.CreateElement("ExternalProject"); externalProjectDocument.AppendChild(externalProject); externalProject.SetAttribute("Name", definition.Name); if (definition.PostBuildHook) { externalProject.SetAttribute("PostBuildHook", "True"); } var externalProjectServices = externalProjectDocument.CreateElement("Services"); externalProject.AppendChild(externalProjectServices); // Just import all declared services as available, regardless of conflicts or // requirements. We don't have a clean way of automatically translating // services for packages (it has to be done manually because services can // change the resulting code that's built). So that things work 95% of time, // just declare all services available for projects included via the automatic // packaging mechanism. var servicesToDeclare = new List <string>(); var servicesDeclared = document.Root.Element(XName.Get("Services")); if (servicesDeclared != null) { foreach (var serviceElement in servicesDeclared.Elements().Where(x => x.Name.LocalName == "Service")) { servicesToDeclare.Add(serviceElement.Attribute(XName.Get("Name")).Value); } } foreach (var serviceToDeclare in servicesToDeclare) { var serviceElem = externalProjectDocument.CreateElement("Service"); serviceElem.SetAttribute("Name", serviceToDeclare); var defaultForRoot = externalProjectDocument.CreateElement("DefaultForRoot"); defaultForRoot.InnerText = "True"; serviceElem.AppendChild(defaultForRoot); externalProjectServices.AppendChild(serviceElem); } var pathPrefix = this.m_ProjectOutputPathCalculator.GetProjectOutputPathPrefix(platform, definition, document, true); var assemblyName = this.m_ProjectOutputPathCalculator.GetProjectAssemblyName(platform, definition, document); var outputMode = this.m_ProjectOutputPathCalculator.GetProjectOutputMode(document); var assemblyFilesToCopy = new[] { assemblyName + ".exe", assemblyName + ".dll", assemblyName + ".dll.config", assemblyName + ".dll.mdb", assemblyName + ".pdb", assemblyName + ".xml", }; // Copy the assembly itself out to the package. switch (outputMode) { case OutputPathMode.BinConfiguration: { // In this configuration, we only ship the binaries for // the default architecture (because that's all we know // about). We also have to assume the binary folder // contains binaries for the desired platform. if (definition.Type == "Library") { // For libraries, we only copy the assembly (and immediately related files) // into it's directory. Native binaries will be expressed through the ExternalProject. foreach (var assemblyFile in assemblyFilesToCopy) { var includeMatch = fileFilter.ApplyInclude("^" + pathPrefix + Regex.Escape(assemblyFile) + "$"); var rewriteMatch = fileFilter.ApplyRewrite("^" + pathPrefix + Regex.Escape(assemblyFile) + "$", definition.Name + "/AnyCPU/" + assemblyFile); if (includeMatch && rewriteMatch) { if (assemblyFile.EndsWith(".dll")) { var binaryEntry = externalProjectDocument.CreateElement("Binary"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\AnyCPU\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } else if (assemblyFile.EndsWith(".dll.config")) { var configEntry = externalProjectDocument.CreateElement("NativeBinary"); configEntry.SetAttribute("Path", definition.Name + "\\AnyCPU\\" + assemblyFile); externalProject.AppendChild(configEntry); } } else if (includeMatch || rewriteMatch) { throw new InvalidOperationException("Automatic filter; only one rule matched."); } } } else { // For executables, we ship everything in the output directory, because we // want the executables to be able to run from the package directory. fileFilter.ApplyInclude("^" + pathPrefix + "(.+)$"); fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/AnyCPU/$2"); // Mark the executable files in the directory as tools that can be executed. foreach (var assemblyFile in assemblyFilesToCopy) { if (assemblyFile.EndsWith(".exe")) { var binaryEntry = externalProjectDocument.CreateElement("Tool"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\AnyCPU\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } } } break; } case OutputPathMode.BinPlatformArchConfiguration: { // In this configuration, we ship binaries for AnyCPU, iPhoneSimulator or all .NET architectures // depending on whether or not the platform produces multiple architectures. On Mono, // we can't use $(Platform) within a reference's path, so we have to keep this path static // for Mono platforms. string pathArchMatch, pathArchReplace, pathArchRuntime; switch (platform.ToLowerInvariant()) { case "ios": { pathArchMatch = "iPhoneSimulator"; pathArchReplace = "iPhoneSimulator"; pathArchRuntime = "iPhoneSimulator"; break; } case "windowsphone": { pathArchMatch = "([^/]+)"; pathArchReplace = "$1"; pathArchRuntime = "$(Platform)"; break; } default: { pathArchMatch = "AnyCPU"; pathArchReplace = "AnyCPU"; pathArchRuntime = "AnyCPU"; break; } } if (definition.Type == "Library") { // For libraries, we only copy the assembly (and immediately related files) // into it's directory. Native binaries will be expressed through the ExternalProject. foreach (var assemblyFile in assemblyFilesToCopy) { var includeMatch = fileFilter.ApplyInclude("^" + pathPrefix + Regex.Escape(assemblyFile) + "$"); var rewriteMatch = fileFilter.ApplyRewrite("^" + pathPrefix + Regex.Escape(assemblyFile) + "$", definition.Name + "/" + pathArchReplace + "/" + assemblyFile); if (includeMatch && rewriteMatch) { if (assemblyFile.EndsWith(".dll")) { var binaryEntry = externalProjectDocument.CreateElement("Binary"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\" + pathArchRuntime + "\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } else if (assemblyFile.EndsWith(".dll.config")) { var configEntry = externalProjectDocument.CreateElement("NativeBinary"); configEntry.SetAttribute("Path", definition.Name + "\\" + pathArchRuntime + "\\" + assemblyFile); externalProject.AppendChild(configEntry); } } else if (includeMatch || rewriteMatch) { throw new InvalidOperationException("Automatic filter; only one rule matched."); } } } else { // For executables, we ship everything in the output directory, because we // want the executables to be able to run from the package directory. fileFilter.ApplyInclude("^" + pathPrefix + "(.+)$"); if (pathArchMatch == "([^/]+)") { fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/" + pathArchReplace + "/$3"); } else { fileFilter.ApplyRewrite("^" + pathPrefix + "(.+)$", definition.Name + "/" + pathArchReplace + "/$2"); } // Mark the executable files in the directory as tools that can be executed. foreach (var assemblyFile in assemblyFilesToCopy) { if (assemblyFile.EndsWith(".exe")) { var binaryEntry = externalProjectDocument.CreateElement("Tool"); binaryEntry.SetAttribute("Name", assemblyFile.Substring(0, assemblyFile.Length - 4)); binaryEntry.SetAttribute("Path", definition.Name + "\\" + pathArchRuntime + "\\" + assemblyFile); externalProject.AppendChild(binaryEntry); } } } break; } case OutputPathMode.BinProjectPlatformArchConfiguration: { throw new NotSupportedException(); break; } } // Convert all of the known references into references within the external project. var definitionsByName = definitions.ToDictionarySafe( k => k.Name, v => v, (dict, x) => { var existing = dict[x.Name]; var tried = x; RedirectableConsole.WriteLine("WARNING: There is more than one project with the name " + x.Name + " (first project loaded from " + tried.AbsolutePath + ", " + "skipped loading second project from " + existing.AbsolutePath + ")"); }); foreach (var reference in document.XPathSelectElements("/Project/References/Reference")) { var includeAttribute = reference.Attribute(XName.Get("Include")); if (includeAttribute != null) { if (definitionsByName.ContainsKey(includeAttribute.Value)) { var targetDefinition = definitionsByName[includeAttribute.Value]; // If the targeted reference is an include project, skip it. if (targetDefinition == null || targetDefinition.Type != "Include") { // This reference will be converted to an external project, // so add a reference to it (in case it contains native binaries // which need to be copied out). var referenceEntry = externalProjectDocument.CreateElement("Reference"); referenceEntry.SetAttribute("Include", includeAttribute.Value); externalProject.AppendChild(referenceEntry); } } } } // Copy out any files that are marked with copy-on-build flag. var detector = new PlatformAndServiceActiveDetection(); var xmlDocument = new XmlDocument(); xmlDocument.Load(definition.DefinitionPath); var servicesInput = this.m_ServiceInputGenerator.Generate(xmlDocument, definition.Name, services); var activeServicesElement = servicesInput.ChildNodes.OfType <XmlElement>().FirstOrDefault(x => x.LocalName == "ActiveServicesNames"); var activeServices = activeServicesElement.InnerText; foreach (var file in document.XPathSelectElements("/Project/Files/*")) { var copyOnBuild = file.XPathSelectElement("CopyToOutputDirectory"); if (copyOnBuild == null) { continue; } if (copyOnBuild.Value != "PreserveNewest" && copyOnBuild.Value != "Always") { continue; } var platformsElement = file.XPathSelectElement("Platforms"); var includePlatformsElement = file.XPathSelectElement("IncludePlatforms"); var excludePlatformsElement = file.XPathSelectElement("ExcludePlatforms"); var servicesElement = file.XPathSelectElement("Services"); var includeServicesElement = file.XPathSelectElement("IncludeServices"); var excludeServicesElement = file.XPathSelectElement("ExcludeServices"); var platformsString = platformsElement != null ? platformsElement.Value : string.Empty; var includePlatformsString = includePlatformsElement != null ? includePlatformsElement.Value : string.Empty; var excludePlatformsString = excludePlatformsElement != null ? excludePlatformsElement.Value : string.Empty; var servicesString = servicesElement != null ? servicesElement.Value : string.Empty; var includeServicesString = includeServicesElement != null ? includeServicesElement.Value : string.Empty; var excludeServicesString = excludeServicesElement != null ? excludeServicesElement.Value : string.Empty; if (detector.ProjectAndServiceIsActive( platformsString, includePlatformsString, excludePlatformsString, servicesString, includeServicesString, excludeServicesString, platform, activeServices)) { var include = file.Attribute(XName.Get("Include")); var linkElement = file.XPathSelectElement("Link"); var link = linkElement != null ? linkElement.Value : include.Value; var fileInfo = new FileInfo(Path.Combine( definition.AbsolutePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar), include.Value.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar))); if (definition.Type == "Library") { // For libraries, we're copying the content so that applications using // the libraries will have the content. This is most often used to // ship native binaries (although NativeBinary in external projects now // supersedes this). if (link.Contains('/') || link.Contains('\\')) { RedirectableConsole.WriteLine( "WARNING: Copy-on-build file '" + link + "' in library project which " + "does not output to root of project detected. This is not supported."); } else { if (fileInfo.Name != link) { RedirectableConsole.WriteLine( "WARNING: Copy-on-build file in library project does not have the same " + "name when copied to build directory. This is not supported."); } else { var sourcePath = fileInfo.FullName; sourcePath = sourcePath.Substring(rootPath.Length).Replace('\\', '/').TrimStart('/'); var destPath = Path.Combine("_AutomaticExternals", sourcePath); var sourcePathRegex = this.ConvertPathWithMSBuildVariablesFind(sourcePath); var destPathRegex = this.ConvertPathWithMSBuildVariablesReplace(destPath.Replace('\\', '/')); var includeMatch = fileFilter.ApplyInclude(sourcePathRegex); fileFilter.ApplyRewrite(sourcePathRegex, destPathRegex); if (includeMatch) { var nativeBinaryEntry = externalProjectDocument.CreateElement("NativeBinary"); nativeBinaryEntry.SetAttribute("Path", destPath); externalProject.AppendChild(nativeBinaryEntry); } else { throw new InvalidOperationException( "File not found at " + sourcePath + " when converting " + "copy-on-build file in library project."); } } } } } } // Write out the external project to a temporary file and include it. var name = Path.GetRandomFileName() + "_" + definition.Name + ".xml"; var temp = Path.Combine(Path.GetTempPath(), name); temporaryFiles.Add(temp); using (var writer = XmlWriter.Create(temp, new XmlWriterSettings { Indent = true, IndentChars = " " })) { externalProjectDocument.WriteTo(writer); } fileFilter.AddManualMapping(temp, "Build/Projects/" + definition.Name + ".definition"); }
public void Autopackage( string workingDirectory, FileFilter fileFilter, Execution execution, ModuleInfo module, string rootPath, string platform, string packageFormat, List <string> temporaryFiles) { var definitions = module.GetDefinitionsRecursively(platform).ToArray(); var loadedProjects = new List <LoadedDefinitionInfo>(); foreach (var definition in definitions) { RedirectableConsole.WriteLine("Loading: " + definition.Name); loadedProjects.Add( this.m_ProjectLoader.Load( platform, module, definition)); } var serviceManager = new ServiceManager(platform); List <Service> services; serviceManager.SetRootDefinitions(module.GetDefinitions()); var enabledServices = execution.EnabledServices.ToArray(); var disabledServices = execution.DisabledServices.ToArray(); foreach (var service in enabledServices) { serviceManager.EnableService(service); } foreach (var service in disabledServices) { serviceManager.DisableService(service); } if (execution.DebugServiceResolution) { serviceManager.EnableDebugInformation(); } services = serviceManager.CalculateDependencyGraph(loadedProjects.Select(x => x.Project).ToList()); foreach (var service in services) { if (service.ServiceName != null) { RedirectableConsole.WriteLine("Enabled service: " + service.FullName); } } var packagePaths = module.Packages .Select(x => new DirectoryInfo(System.IO.Path.Combine(module.Path, x.Folder)).FullName) .ToArray(); foreach (var definition in definitions) { if (definition.SkipAutopackage) { RedirectableConsole.WriteLine("Skipping: " + definition.Name); continue; } var definitionNormalizedPath = new FileInfo(definition.AbsolutePath).FullName; if (packagePaths.Any(definitionNormalizedPath.StartsWith)) { RedirectableConsole.WriteLine("Skipping: " + definition.Name + " (part of another package)"); continue; } switch (definition.Type) { case "External": RedirectableConsole.WriteLine("Packaging: " + definition.Name); this.AutomaticallyPackageExternalProject(definitions, services, fileFilter, rootPath, platform, definition, temporaryFiles); break; case "Include": RedirectableConsole.WriteLine("Packaging: " + definition.Name); this.AutomaticallyPackageIncludeProject(definitions, services, fileFilter, rootPath, platform, definition); break; case "Content": RedirectableConsole.WriteLine("Content project definition skipped: " + definition.Name); break; default: RedirectableConsole.WriteLine("Packaging: " + definition.Name); this.AutomaticallyPackageNormalProject(definitions, services, fileFilter, rootPath, platform, definition, temporaryFiles); break; } } // If there is no Module.xml in the source mappings already, then copy the current module. if (!fileFilter.ContainsTargetPath("Build/Module.xml")) { fileFilter.AddManualMapping(Path.Combine(module.Path, "Build", "Module.xml"), "Build/Module.xml"); } }