public bool BuildNativeImages(BundleRoot root) { var success = true; foreach (var runtime in root.Runtimes) { NuGetDependencyResolver resolver; if (!_resolverLookup.TryGetValue(runtime.Framework, out resolver)) { throw new InvalidOperationException("No matching framework is found for " + runtime.Framework); } var runtimeBin = Path.Combine(runtime.TargetPath, "bin"); var options = new CrossgenOptions() { CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"), InputPaths = ResolveOutputAssemblies(root, resolver), RuntimePath = runtimeBin, Symbols = false }; var crossgenManager = new CrossgenManager(options); success &= crossgenManager.GenerateNativeImages(); if (!success) { return false; } } return success; }
public void PostProcess(BundleRoot root) { // If --wwwroot-out doesn't have a non-empty value, we don't need a public app folder in output if (string.IsNullOrEmpty(WwwRootOut)) { return; } Runtime.Project project; if (!_projectResolver.TryResolveProject(_libraryDescription.Identity.Name, out project)) { throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } // Construct path to public app folder, which contains content files and tool dlls // The name of public app folder is specified with "--appfolder" option // Default name of public app folder is the same as main project var wwwRootOutPath = Path.Combine(root.OutputPath, WwwRootOut); // Delete old public app folder because we don't want leftovers from previous operations root.Operations.Delete(wwwRootOutPath); Directory.CreateDirectory(wwwRootOutPath); // Copy content files (e.g. html, js and images) of main project into public app folder CopyContentFiles(root, project, wwwRootOutPath); GenerateWebConfigFileForWwwRootOut(root, project, wwwRootOutPath); CopyAspNetLoaderDll(root, wwwRootOutPath); }
public BundleRuntime(BundleRoot root, FrameworkName frameworkName, string runtimePath) { _frameworkName = frameworkName; _runtimePath = runtimePath; Name = new DirectoryInfo(_runtimePath).Name; TargetPath = Path.Combine(root.TargetPackagesPath, Name); }
public bool BuildNativeImages(BundleRoot root) { var success = true; foreach (var runtime in root.Runtimes) { NuGetDependencyResolver resolver; if (!_resolverLookup.TryGetValue(runtime.Framework, out resolver)) { throw new InvalidOperationException("No matching framework is found for " + runtime.Framework); } var runtimeBin = Path.Combine(runtime.TargetPath, "bin"); var options = new CrossgenOptions() { CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"), InputPaths = ResolveOutputAssemblies(root, resolver), RuntimePath = runtimeBin, Symbols = false }; var crossgenManager = new CrossgenManager(options); success &= crossgenManager.GenerateNativeImages(); if (!success) { return(false); } } return(success); }
private void EmitSource(BundleRoot root) { root.Reports.Quiet.WriteLine(" Copying source code from {0} dependency {1}", _libraryDescription.Type, _libraryDescription.Identity.Name); Runtime.Project project; if (!_projectResolver.TryResolveProject(_libraryDescription.Identity.Name, out project)) { throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } var targetName = project.Name; TargetPath = Path.Combine(root.OutputPath, BundleRoot.AppRootName, "src", targetName); // If root.OutputPath is specified by --out option, it might not be a full path TargetPath = Path.GetFullPath(TargetPath); root.Reports.Quiet.WriteLine(" Source {0}", _libraryDescription.Path.Bold()); root.Reports.Quiet.WriteLine(" Target {0}", TargetPath); root.Operations.Delete(TargetPath); CopyProject(root, project, TargetPath, includeSource: true); CopyRelativeSources(project); UpdateWebRoot(root, TargetPath); _applicationBase = Path.Combine("..", BundleRoot.AppRootName, "src", project.Name); }
private static string GetBootstrapperVersion(BundleRoot root) { // Use version of Microsoft.AspNet.Loader.IIS.Interop as version of bootstrapper var package = root.Packages.SingleOrDefault( x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop")); return(package == null ? string.Empty : package.Library.Version.ToString()); }
bool TryAddRuntime(BundleRoot root, FrameworkName frameworkName, string runtimePath) { if (!Directory.Exists(runtimePath)) { return(false); } root.Runtimes.Add(new BundleRuntime(root, frameworkName, runtimePath)); return(true); }
public void Emit(BundleRoot root) { root.Reports.Quiet.WriteLine("Using {0} dependency {1}", _libraryDescription.Type, Library); foreach (var context in root.LibraryDependencyContexts[Library]) { root.Reports.Quiet.WriteLine(" Copying files for {0}", context.FrameworkName.ToString().Yellow().Bold()); Emit(root, context.PackageAssemblies[Library.Name]); root.Reports.Quiet.WriteLine(); } }
private void CopyContentFiles(BundleRoot root, Runtime.Project project, string targetFolderPath) { root.Reports.Quiet.WriteLine("Copying contents of {0} dependency {1} to {2}", _libraryDescription.Type, _libraryDescription.Identity.Name, targetFolderPath); var contentSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot); root.Reports.Quiet.WriteLine(" Source {0}", contentSourcePath); root.Reports.Quiet.WriteLine(" Target {0}", targetFolderPath); root.Operations.Copy(contentSourcePath, targetFolderPath); }
private void CopyProject(BundleRoot root, Runtime.Project project, string targetPath, bool includeSource) { // A set of excluded files/directories used as a filter when doing copy var excludeSet = new HashSet <string>(project.BundleExcludeFiles, StringComparer.OrdinalIgnoreCase); var contentFiles = new HashSet <string>(project.ContentFiles, StringComparer.OrdinalIgnoreCase); // If a public folder is specified with 'webroot' or '--wwwroot', we ignore it when copying project files var wwwRootPath = string.Empty; if (!string.IsNullOrEmpty(WwwRoot)) { wwwRootPath = Path.Combine(project.ProjectDirectory, WwwRoot); wwwRootPath = PathUtility.EnsureTrailingSlash(wwwRootPath); } // If project root is used as value of '--wwwroot', we shouldn't exclude it when copying if (string.Equals(wwwRootPath, PathUtility.EnsureTrailingSlash(project.ProjectDirectory))) { wwwRootPath = string.Empty; } root.Operations.Copy(project.ProjectDirectory, targetPath, itemPath => { // If current file/folder is in the exclusion list, we don't copy it if (excludeSet.Contains(itemPath)) { return(false); } // If current file is in the public folder, we don't copy it to destination project if (!string.IsNullOrEmpty(wwwRootPath) && itemPath.StartsWith(wwwRootPath)) { return(false); } // The full path of target generated by copy operation should also be excluded var targetFullPath = itemPath.Replace(project.ProjectDirectory, TargetPath); excludeSet.Add(targetFullPath); if (includeSource) { return(true); } if (Directory.Exists(itemPath)) { return(true); } return(contentFiles.Contains(itemPath)); }); }
private void UpdateWebRoot(BundleRoot root, string targetPath) { // Update the 'webroot' property, which was specified with '--wwwroot-out' option if (!string.IsNullOrEmpty(WwwRootOut)) { var targetProjectJson = Path.Combine(targetPath, Runtime.Project.ProjectFileName); UpdateJson(targetProjectJson, jsonObj => { var targetWebRootPath = Path.Combine(root.OutputPath, WwwRootOut); jsonObj["webroot"] = PathUtility.GetRelativePath(targetProjectJson, targetWebRootPath, separator: '/'); }); } }
public void Emit(BundleRoot root) { root.Reports.Quiet.WriteLine("Using {0} dependency {1} for {2}", _libraryDescription.Type, _libraryDescription.Identity, _libraryDescription.Framework.ToString().Yellow().Bold()); if (root.NoSource) { EmitNupkg(root); } else { EmitSource(root); } root.Reports.Quiet.WriteLine(); }
/// <summary> /// This is a helper method for looking up directories that directly contains assemblies that would be loaded /// given the bundled runtime framework. We should run crossgen on these folders /// </summary> private IEnumerable <string> ResolveOutputAssemblies(BundleRoot root, NuGetDependencyResolver resolver) { var outputPathsMap = root.Packages .ToDictionary( pkg => pkg.Library, pkg => pkg.TargetPath ); var result = new HashSet <string>(); var libraryNotInOutput = new List <Library>(); var missingOutputFolder = new List <string>(); foreach (var dependency in resolver.PackageAssemblyLookup.Values) { var libId = dependency.Library.Identity; var libPath = dependency.Library.Path; var assemblyDir = Path.GetDirectoryName(dependency.Path); var assemblySelection = assemblyDir.Substring(libPath.Length); string outputLibLocation; if (!outputPathsMap.TryGetValue(libId, out outputLibLocation)) { libraryNotInOutput.Add(libId); continue; } var output = outputLibLocation + assemblySelection; if (!Directory.Exists(output)) { missingOutputFolder.Add(output); } else { result.Add(output); } } if (libraryNotInOutput.Any()) { throw new InvalidOperationException(string.Format("Library {0} cannot be found in the bundled output.", string.Join(", ", libraryNotInOutput))); } if (missingOutputFolder.Any()) { throw new InvalidOperationException("Bundled output does not contain directory:\n" + string.Join("\n", missingOutputFolder)); } return(result); }
public void Emit(BundleRoot root) { root.Reports.Quiet.WriteLine("Bundling runtime {0}", Name); if (Directory.Exists(TargetPath)) { root.Reports.Quiet.WriteLine(" {0} already exists.", TargetPath); return; } if (!Directory.Exists(TargetPath)) { Directory.CreateDirectory(TargetPath); } new BundleOperations().Copy(_runtimePath, TargetPath); }
private void CopyFile(BundleRoot root, string srcPath, string targetPath, bool overwrite) { var targetFolder = Path.GetDirectoryName(targetPath); Directory.CreateDirectory(targetFolder); if (File.Exists(targetPath)) { if (overwrite) { File.Delete(targetPath); } else { root.Reports.Quiet.WriteLine(" {0} already exists", targetPath); return; } } File.Copy(srcPath, targetPath); }
/// <summary> /// This is the factory method to instantiate a PackNativeManager, if parameters are in invalid state and native /// generation cannot be performed, it would return null /// </summary> public static NativeImageGenerator Create(BundleOptions options, BundleRoot root, IEnumerable<DependencyContext> contexts) { if (options.Runtimes.Count() == 0) { options.Reports.Information.WriteLine( "Please provide target CoreCLR runtimes using --runtime flags".Yellow()); return null; } foreach (var runtime in root.Runtimes) { var frameworkName = runtime.Framework; // NOTE: !IsDesktop == IsCore and only Core packages can be crossgened at least for now if (VersionUtility.IsDesktop(frameworkName)) { options.Reports.Information.WriteLine( "Native image generation is only supported for .NET Core flavors.".Yellow()); return null; } } var duplicates = options.Runtimes .GroupBy(r => CrossgenManager.ResolveProcessorArchitecture(r)) .Where(g => g.Count() > 1); if (duplicates.Any()) { var message = "The following runtimes will result in output conflicts. Please provide distinct runtime flavor for each processor architecture:\n" + string.Join("\n", duplicates.Select( g => string.Format("Architecture: {0}\nRuntimes: {1}", g.Key, string.Join(", ", g)))); options.Reports.Information.WriteLine(message.Yellow()); return null; } var contextMap = contexts.ToDictionary( context => context.FrameworkName, context => context.NuGetDependencyResolver ); return new NativeImageGenerator(contextMap); }
/// <summary> /// This is the factory method to instantiate a PackNativeManager, if parameters are in invalid state and native /// generation cannot be performed, it would return null /// </summary> public static NativeImageGenerator Create(BundleOptions options, BundleRoot root, IEnumerable <DependencyContext> contexts) { if (options.Runtimes.Count() == 0) { options.Reports.Information.WriteLine( "Please provide target CoreCLR runtimes using --runtime flags".Yellow()); return(null); } foreach (var runtime in root.Runtimes) { var frameworkName = runtime.Framework; // NOTE: !IsDesktop == IsCore and only Core packages can be crossgened at least for now if (VersionUtility.IsDesktop(frameworkName)) { options.Reports.Information.WriteLine( "Native image generation is only supported for .NET Core flavors.".Yellow()); return(null); } } var duplicates = options.Runtimes .GroupBy(r => CrossgenManager.ResolveProcessorArchitecture(r)) .Where(g => g.Count() > 1); if (duplicates.Any()) { var message = "The following runtimes will result in output conflicts. Please provide distinct runtime flavor for each processor architecture:\n" + string.Join("\n", duplicates.Select( g => string.Format("Architecture: {0}\nRuntimes: {1}", g.Key, string.Join(", ", g)))); options.Reports.Information.WriteLine(message.Yellow()); return(null); } var contextMap = contexts.ToDictionary( context => context.FrameworkName, context => context.NuGetDependencyResolver ); return(new NativeImageGenerator(contextMap)); }
private void CopyFolder(BundleRoot root, string srcFolder, string targetFolder) { if (!Directory.Exists(srcFolder)) { return; } if (Directory.Exists(targetFolder)) { if (root.Overwrite) { root.Operations.Delete(targetFolder); } else { root.Reports.Quiet.WriteLine(" {0} already exists", targetFolder); return; } } Directory.CreateDirectory(targetFolder); root.Operations.Copy(srcFolder, targetFolder); }
private static void CopyAspNetLoaderDll(BundleRoot root, string wwwRootOutPath) { // Tool dlls including AspNet.Loader.dll go to bin folder under public app folder var wwwRootOutBinPath = Path.Combine(wwwRootOutPath, "bin"); // Copy Microsoft.AspNet.Loader.IIS.Interop/tools/*.dll into bin to support AspNet.Loader.dll var package = root.Packages.SingleOrDefault( x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop")); if (package == null) { return; } var resolver = new DefaultPackagePathResolver(root.SourcePackagesPath); var packagePath = resolver.GetInstallPath(package.Library.Name, package.Library.Version); var packageToolsPath = Path.Combine(packagePath, "tools"); if (Directory.Exists(packageToolsPath)) { foreach (var packageToolFile in Directory.EnumerateFiles(packageToolsPath, "*.dll").Select(Path.GetFileName)) { // Create the bin folder only when we need to put something inside it if (!Directory.Exists(wwwRootOutBinPath)) { Directory.CreateDirectory(wwwRootOutBinPath); } // Copy to bin folder under public app folder File.Copy( Path.Combine(packageToolsPath, packageToolFile), Path.Combine(wwwRootOutBinPath, packageToolFile), overwrite: true); } } }
private void Emit(BundleRoot root, IEnumerable <PackageAssembly> assemblies) { var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); TargetPath = resolver.GetInstallPath(Library.Name, Library.Version); root.Reports.Quiet.WriteLine(" Source: {0}", _libraryDescription.Path); root.Reports.Quiet.WriteLine(" Target: {0}", TargetPath); Directory.CreateDirectory(TargetPath); // Copy nuspec var nuspecName = resolver.GetManifestFileName(Library.Name, Library.Version); root.Reports.Quiet.WriteLine(" File: {0}", nuspecName.Bold()); CopyFile(root, Path.Combine(_libraryDescription.Path, nuspecName), Path.Combine(TargetPath, nuspecName), root.Overwrite); // Copy assemblies for current framework foreach (var assembly in assemblies) { root.Reports.Quiet.WriteLine(" File: {0}", assembly.RelativePath.Bold()); var targetAssemblyPath = Path.Combine(TargetPath, assembly.RelativePath); CopyFile(root, assembly.Path, targetAssemblyPath, root.Overwrite); } // Special cases var specialFolders = new[] { "native", "InteropAssemblies", "redist", Path.Combine("lib", "contract") }; foreach (var folder in specialFolders) { var srcFolder = Path.Combine(_libraryDescription.Path, folder); var targetFolder = Path.Combine(TargetPath, folder); CopyFolder(root, srcFolder, targetFolder); } }
private void Emit(BundleRoot root, IEnumerable<PackageAssembly> assemblies) { var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); TargetPath = resolver.GetInstallPath(Library.Name, Library.Version); root.Reports.Quiet.WriteLine(" Source: {0}", _libraryDescription.Path); root.Reports.Quiet.WriteLine(" Target: {0}", TargetPath); Directory.CreateDirectory(TargetPath); // Copy nuspec var nuspecName = resolver.GetManifestFileName(Library.Name, Library.Version); root.Reports.Quiet.WriteLine(" File: {0}", nuspecName.Bold()); CopyFile(root, Path.Combine(_libraryDescription.Path, nuspecName), Path.Combine(TargetPath, nuspecName), root.Overwrite); // Copy assemblies for current framework foreach (var assembly in assemblies) { root.Reports.Quiet.WriteLine(" File: {0}", assembly.RelativePath.Bold()); var targetAssemblyPath = Path.Combine(TargetPath, assembly.RelativePath); CopyFile(root, assembly.Path, targetAssemblyPath, root.Overwrite); } // Special cases var specialFolders = new[] { "native", "InteropAssemblies", "redist", Path.Combine("lib", "contract") }; foreach (var folder in specialFolders) { var srcFolder = Path.Combine(_libraryDescription.Path, folder); var targetFolder = Path.Combine(TargetPath, folder); CopyFolder(root, srcFolder, targetFolder); } }
private void EmitNupkg(BundleRoot root) { root.Reports.Quiet.WriteLine(" Packing nupkg from {0} dependency {1}", _libraryDescription.Type, _libraryDescription.Identity.Name); Runtime.Project project; if (!_projectResolver.TryResolveProject(_libraryDescription.Identity.Name, out project)) { throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath); var targetNupkg = resolver.GetPackageFileName(project.Name, project.Version); TargetPath = resolver.GetInstallPath(project.Name, project.Version); root.Reports.Quiet.WriteLine(" Source {0}", _libraryDescription.Path.Bold()); root.Reports.Quiet.WriteLine(" Target {0}", TargetPath); if (Directory.Exists(TargetPath)) { if (root.Overwrite) { root.Operations.Delete(TargetPath); } else { root.Reports.Quiet.WriteLine(" {0} already exists.", TargetPath); return; } } // Generate nupkg from this project dependency var buildOptions = new BuildOptions(); buildOptions.ProjectDir = project.ProjectDirectory; buildOptions.OutputDir = Path.Combine(project.ProjectDirectory, "bin"); buildOptions.Configurations.Add(root.Configuration); buildOptions.Reports = root.Reports; buildOptions.GeneratePackages = true; var buildManager = new BuildManager(root.HostServices, buildOptions); if (!buildManager.Build()) { return; } // Extract the generated nupkg to target path var srcNupkgPath = Path.Combine(buildOptions.OutputDir, root.Configuration, targetNupkg); var targetNupkgPath = resolver.GetPackageFilePath(project.Name, project.Version); var hashFile = resolver.GetHashPath(project.Name, project.Version); using (var sourceStream = new FileStream(srcNupkgPath, FileMode.Open, FileAccess.Read)) { using (var archive = new ZipArchive(sourceStream, ZipArchiveMode.Read)) { root.Operations.ExtractNupkg(archive, TargetPath); } } using (var sourceStream = new FileStream(srcNupkgPath, FileMode.Open, FileAccess.Read)) { using (var targetStream = new FileStream(targetNupkgPath, FileMode.Create, FileAccess.Write, FileShare.None)) { sourceStream.CopyTo(targetStream); } sourceStream.Seek(0, SeekOrigin.Begin); var sha512Bytes = SHA512.Create().ComputeHash(sourceStream); File.WriteAllText(hashFile, Convert.ToBase64String(sha512Bytes)); } // Copy content files (e.g. html, js and images) of main project into "root" folder of the exported package var rootFolderPath = Path.Combine(TargetPath, "root"); var rootProjectJson = Path.Combine(rootFolderPath, Runtime.Project.ProjectFileName); CopyProject(root, project, rootFolderPath, includeSource: false); UpdateWebRoot(root, rootFolderPath); UpdateJson(rootProjectJson, jsonObj => { // Update the project entrypoint jsonObj["entryPoint"] = _libraryDescription.Identity.Name; // Set mark this as non loadable jsonObj["loadable"] = false; // Update the dependencies node to reference the main project var deps = new JObject(); jsonObj["dependencies"] = deps; deps[_libraryDescription.Identity.Name] = _libraryDescription.Identity.Version.ToString(); }); _applicationBase = Path.Combine("..", BundleRoot.AppRootName, "packages", resolver.GetPackageDirectory(_libraryDescription.Identity.Name, _libraryDescription.Identity.Version), "root"); }
private void GenerateWebConfigFileForWwwRootOut(BundleRoot root, Runtime.Project project, string wwwRootOutPath) { // Generate web.config for public app folder var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config"); var wwwRootSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot); var webConfigFilePath = Path.Combine(wwwRootSourcePath, "web.config"); XDocument xDoc; if (File.Exists(webConfigFilePath)) { xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath)); } else { xDoc = new XDocument(); } if (xDoc.Root == null) { xDoc.Add(new XElement("configuration")); } if (xDoc.Root.Name != "configuration") { throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file"); } var appSettingsElement = GetOrAddElement(parent: xDoc.Root, name: "appSettings"); var relativePackagesPath = PathUtility.GetRelativePath(wwwRootOutWebConfigFilePath, root.TargetPackagesPath); var defaultRuntime = root.Runtimes.FirstOrDefault(); var keyValuePairs = new Dictionary <string, string>() { { Runtime.Constants.WebConfigKpmPackagePath, relativePackagesPath }, { Runtime.Constants.WebConfigBootstrapperVersion, GetBootstrapperVersion(root) }, { Runtime.Constants.WebConfigRuntimePath, relativePackagesPath }, { Runtime.Constants.WebConfigRuntimeVersion, GetRuntimeVersion(defaultRuntime) }, { Runtime.Constants.WebConfigRuntimeFlavor, GetRuntimeFlavor(defaultRuntime) }, { Runtime.Constants.WebConfigRuntimeAppBase, _applicationBase }, }; foreach (var pair in keyValuePairs) { var addElement = appSettingsElement.Elements() .Where(x => x.Name == "add" && x.Attribute("key").Value == pair.Key) .SingleOrDefault(); if (addElement == null) { addElement = new XElement("add"); addElement.SetAttributeValue("key", pair.Key); appSettingsElement.Add(addElement); } addElement.SetAttributeValue("value", pair.Value); } var xmlWriterSettings = new XmlWriterSettings { Indent = true, ConformanceLevel = ConformanceLevel.Auto }; using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings)) { xDoc.WriteTo(xmlWriter); } }
/// <summary> /// This is a helper method for looking up directories that directly contains assemblies that would be loaded /// given the bundled runtime framework. We should run crossgen on these folders /// </summary> private IEnumerable<string> ResolveOutputAssemblies(BundleRoot root, NuGetDependencyResolver resolver) { var outputPathsMap = root.Packages .ToDictionary( pkg => pkg.Library, pkg => pkg.TargetPath ); var result = new HashSet<string>(); var libraryNotInOutput = new List<Library>(); var missingOutputFolder = new List<string>(); foreach (var dependency in resolver.PackageAssemblyLookup.Values) { var libId = dependency.Library.Identity; var libPath = dependency.Library.Path; var assemblyDir = Path.GetDirectoryName(dependency.Path); var assemblySelection = assemblyDir.Substring(libPath.Length); string outputLibLocation; if (!outputPathsMap.TryGetValue(libId, out outputLibLocation)) { libraryNotInOutput.Add(libId); continue; } var output = outputLibLocation + assemblySelection; if (!Directory.Exists(output)) { missingOutputFolder.Add(output); } else { result.Add(output); } } if (libraryNotInOutput.Any()) { throw new InvalidOperationException(string.Format("Library {0} cannot be found in the bundled output.", string.Join(", ", libraryNotInOutput))); } if (missingOutputFolder.Any()) { throw new InvalidOperationException("Bundled output does not contain directory:\n" + string.Join("\n", missingOutputFolder)); } return result; }
bool TryAddRuntime(BundleRoot root, FrameworkName frameworkName, string runtimePath) { if (!Directory.Exists(runtimePath)) { return false; } root.Runtimes.Add(new BundleRuntime(root, frameworkName, runtimePath)); return true; }
public bool Bundle() { Runtime.Project project; if (!Runtime.Project.TryGetProject(_options.ProjectDir, out project)) { _options.Reports.Error.WriteLine("Unable to locate {0}.'".Red(), Runtime.Project.ProjectFileName); return false; } // '--wwwroot' option can override 'webroot' property in project.json _options.WwwRoot = _options.WwwRoot ?? project.WebRoot; _options.WwwRootOut = _options.WwwRootOut ?? _options.WwwRoot; if (string.IsNullOrEmpty(_options.WwwRoot) && !string.IsNullOrEmpty(_options.WwwRootOut)) { _options.Reports.Error.WriteLine( "'--wwwroot-out' option can be used only when the '--wwwroot' option or 'webroot' in project.json is specified.".Red()); return false; } if (!string.IsNullOrEmpty(_options.WwwRoot) && !Directory.Exists(Path.Combine(project.ProjectDirectory, _options.WwwRoot))) { _options.Reports.Error.WriteLine( "The specified wwwroot folder '{0}' doesn't exist in the project directory.".Red(), _options.WwwRoot); return false; } if (string.Equals(_options.WwwRootOut, BundleRoot.AppRootName, StringComparison.OrdinalIgnoreCase)) { _options.Reports.Error.WriteLine( "'{0}' is a reserved folder name. Please choose another name for the wwwroot-out folder.".Red(), BundleRoot.AppRootName); return false; } var sw = Stopwatch.StartNew(); string outputPath = _options.OutputDir; var projectDir = project.ProjectDirectory; var frameworkContexts = new Dictionary<FrameworkName, DependencyContext>(); var root = new BundleRoot(project, outputPath, _hostServices, _options.Reports) { Overwrite = _options.Overwrite, Configuration = _options.Configuration, NoSource = _options.NoSource }; Func<string, string> getVariable = key => { return null; }; if (!ScriptExecutor.Execute(project, "prepare", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } if (!ScriptExecutor.Execute(project, "prebundle", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } foreach (var runtime in _options.Runtimes) { var frameworkName = DependencyContext.GetFrameworkNameForRuntime(Path.GetFileName(runtime)); var runtimeLocated = TryAddRuntime(root, frameworkName, runtime); List<string> runtimeProbePaths = null; if (!runtimeLocated) { runtimeProbePaths = new List<string>(); runtimeProbePaths.Add(runtime); var runtimeHome = Environment.GetEnvironmentVariable(EnvironmentNames.Home); if (string.IsNullOrEmpty(runtimeHome)) { var runtimeGlobalPath = Environment.GetEnvironmentVariable(EnvironmentNames.GlobalPath); #if ASPNETCORE50 runtimeHome = @"%USERPROFILE%\" + Constants.DefaultLocalRuntimeHomeDir + ";" + runtimeGlobalPath; #else var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); runtimeHome = Path.Combine(userProfile, Constants.DefaultLocalRuntimeHomeDir) + ";" + runtimeGlobalPath; #endif } foreach (var portion in runtimeHome.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { var packagesPath = Path.Combine( Environment.ExpandEnvironmentVariables(portion), "runtimes", runtime); if (TryAddRuntime(root, frameworkName, packagesPath)) { runtimeLocated = true; break; } runtimeProbePaths.Add(packagesPath); } } if (!runtimeLocated) { _options.Reports.Error.WriteLine(string.Format("Unable to locate runtime '{0}'", runtime.Red().Bold())); if (runtimeProbePaths != null) { _options.Reports.Error.WriteLine(string.Format("Locations probed:{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, runtimeProbePaths))); } return false; } if (!project.GetTargetFrameworks().Any(x => x.FrameworkName == frameworkName)) { _options.Reports.Error.WriteLine( string.Format("'{0}' is not a target framework of the project being bundled", frameworkName.ToString().Red().Bold())); return false; } if (!frameworkContexts.ContainsKey(frameworkName)) { frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName); } } // If there is no target framework filter specified with '--runtime', // the bundled output targets all frameworks specified in project.json if (!_options.Runtimes.Any()) { foreach (var frameworkInfo in project.GetTargetFrameworks()) { if (!frameworkContexts.ContainsKey(frameworkInfo.FrameworkName)) { frameworkContexts[frameworkInfo.FrameworkName] = CreateDependencyContext(project, frameworkInfo.FrameworkName); } } } if (!frameworkContexts.Any()) { var frameworkName = DependencyContext.GetFrameworkNameForRuntime(Constants.RuntimeNamePrefix + "clr-win-x86.*"); frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName); } root.SourcePackagesPath = frameworkContexts.First().Value.PackagesDirectory; bool anyUnresolvedDependency = false; foreach (var dependencyContext in frameworkContexts.Values) { // If there's any unresolved dependencies then complain and keep working if (dependencyContext.DependencyWalker.Libraries.Any(l => !l.Resolved)) { anyUnresolvedDependency = true; var message = "Warning: " + dependencyContext.DependencyWalker.GetMissingDependenciesWarning( dependencyContext.FrameworkName); _options.Reports.Quiet.WriteLine(message.Yellow()); } foreach (var libraryDescription in dependencyContext.NuGetDependencyResolver.Dependencies) { IList<DependencyContext> contexts; if (!root.LibraryDependencyContexts.TryGetValue(libraryDescription.Identity, out contexts)) { root.Packages.Add(new BundlePackage(libraryDescription)); contexts = new List<DependencyContext>(); root.LibraryDependencyContexts[libraryDescription.Identity] = contexts; } contexts.Add(dependencyContext); } foreach (var libraryDescription in dependencyContext.ProjectReferenceDependencyProvider.Dependencies) { if (!root.Projects.Any(p => p.Name == libraryDescription.Identity.Name)) { var bundleProject = new BundleProject( dependencyContext.ProjectReferenceDependencyProvider, dependencyContext.ProjectResolver, libraryDescription); if (bundleProject.Name == project.Name) { bundleProject.WwwRoot = _options.WwwRoot; bundleProject.WwwRootOut = _options.WwwRootOut; } root.Projects.Add(bundleProject); } } } NativeImageGenerator nativeImageGenerator = null; if (_options.Native) { nativeImageGenerator = NativeImageGenerator.Create(_options, root, frameworkContexts.Values); if (nativeImageGenerator == null) { _options.Reports.Error.WriteLine("Fail to initiate native image generation process.".Red()); return false; } } root.Emit(); if (!ScriptExecutor.Execute(project, "postbundle", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return false; } if (_options.Native && !nativeImageGenerator.BuildNativeImages(root)) { _options.Reports.Error.WriteLine("Native image generation failed."); return false; } sw.Stop(); _options.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed); return !anyUnresolvedDependency; }
private static string GetBootstrapperVersion(BundleRoot root) { // Use version of Microsoft.AspNet.Loader.IIS.Interop as version of bootstrapper var package = root.Packages.SingleOrDefault( x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop")); return package == null ? string.Empty : package.Library.Version.ToString(); }
public bool Bundle() { Runtime.Project project; if (!Runtime.Project.TryGetProject(_options.ProjectDir, out project)) { _options.Reports.Error.WriteLine("Unable to locate {0}.'".Red(), Runtime.Project.ProjectFileName); return(false); } // '--wwwroot' option can override 'webroot' property in project.json _options.WwwRoot = _options.WwwRoot ?? project.WebRoot; _options.WwwRootOut = _options.WwwRootOut ?? _options.WwwRoot; if (string.IsNullOrEmpty(_options.WwwRoot) && !string.IsNullOrEmpty(_options.WwwRootOut)) { _options.Reports.Error.WriteLine( "'--wwwroot-out' option can be used only when the '--wwwroot' option or 'webroot' in project.json is specified.".Red()); return(false); } if (!string.IsNullOrEmpty(_options.WwwRoot) && !Directory.Exists(Path.Combine(project.ProjectDirectory, _options.WwwRoot))) { _options.Reports.Error.WriteLine( "The specified wwwroot folder '{0}' doesn't exist in the project directory.".Red(), _options.WwwRoot); return(false); } if (string.Equals(_options.WwwRootOut, BundleRoot.AppRootName, StringComparison.OrdinalIgnoreCase)) { _options.Reports.Error.WriteLine( "'{0}' is a reserved folder name. Please choose another name for the wwwroot-out folder.".Red(), BundleRoot.AppRootName); return(false); } var sw = Stopwatch.StartNew(); string outputPath = _options.OutputDir; var projectDir = project.ProjectDirectory; var frameworkContexts = new Dictionary <FrameworkName, DependencyContext>(); var root = new BundleRoot(project, outputPath, _hostServices, _options.Reports) { Overwrite = _options.Overwrite, Configuration = _options.Configuration, NoSource = _options.NoSource }; Func <string, string> getVariable = key => { return(null); }; if (!ScriptExecutor.Execute(project, "prepare", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } if (!ScriptExecutor.Execute(project, "prebundle", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } foreach (var runtime in _options.Runtimes) { var frameworkName = DependencyContext.GetFrameworkNameForRuntime(Path.GetFileName(runtime)); var runtimeLocated = TryAddRuntime(root, frameworkName, runtime); List <string> runtimeProbePaths = null; if (!runtimeLocated) { runtimeProbePaths = new List <string>(); runtimeProbePaths.Add(runtime); var runtimeHome = Environment.GetEnvironmentVariable(EnvironmentNames.Home); if (string.IsNullOrEmpty(runtimeHome)) { var runtimeGlobalPath = Environment.GetEnvironmentVariable(EnvironmentNames.GlobalPath); #if ASPNETCORE50 runtimeHome = @"%USERPROFILE%\" + Constants.DefaultLocalRuntimeHomeDir + ";" + runtimeGlobalPath; #else var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); runtimeHome = Path.Combine(userProfile, Constants.DefaultLocalRuntimeHomeDir) + ";" + runtimeGlobalPath; #endif } foreach (var portion in runtimeHome.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { var packagesPath = Path.Combine( Environment.ExpandEnvironmentVariables(portion), "runtimes", runtime); if (TryAddRuntime(root, frameworkName, packagesPath)) { runtimeLocated = true; break; } runtimeProbePaths.Add(packagesPath); } } if (!runtimeLocated) { _options.Reports.Error.WriteLine(string.Format("Unable to locate runtime '{0}'", runtime.Red().Bold())); if (runtimeProbePaths != null) { _options.Reports.Error.WriteLine(string.Format("Locations probed:{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, runtimeProbePaths))); } return(false); } if (!project.GetTargetFrameworks().Any(x => x.FrameworkName == frameworkName)) { _options.Reports.Error.WriteLine( string.Format("'{0}' is not a target framework of the project being bundled", frameworkName.ToString().Red().Bold())); return(false); } if (!frameworkContexts.ContainsKey(frameworkName)) { frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName); } } // If there is no target framework filter specified with '--runtime', // the bundled output targets all frameworks specified in project.json if (!_options.Runtimes.Any()) { foreach (var frameworkInfo in project.GetTargetFrameworks()) { if (!frameworkContexts.ContainsKey(frameworkInfo.FrameworkName)) { frameworkContexts[frameworkInfo.FrameworkName] = CreateDependencyContext(project, frameworkInfo.FrameworkName); } } } if (!frameworkContexts.Any()) { var frameworkName = DependencyContext.GetFrameworkNameForRuntime(Constants.RuntimeNamePrefix + "clr-win-x86.*"); frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName); } root.SourcePackagesPath = frameworkContexts.First().Value.PackagesDirectory; bool anyUnresolvedDependency = false; foreach (var dependencyContext in frameworkContexts.Values) { // If there's any unresolved dependencies then complain and keep working if (dependencyContext.DependencyWalker.Libraries.Any(l => !l.Resolved)) { anyUnresolvedDependency = true; var message = "Warning: " + dependencyContext.DependencyWalker.GetMissingDependenciesWarning( dependencyContext.FrameworkName); _options.Reports.Quiet.WriteLine(message.Yellow()); } foreach (var libraryDescription in dependencyContext.NuGetDependencyResolver.Dependencies) { IList <DependencyContext> contexts; if (!root.LibraryDependencyContexts.TryGetValue(libraryDescription.Identity, out contexts)) { root.Packages.Add(new BundlePackage(libraryDescription)); contexts = new List <DependencyContext>(); root.LibraryDependencyContexts[libraryDescription.Identity] = contexts; } contexts.Add(dependencyContext); } foreach (var libraryDescription in dependencyContext.ProjectReferenceDependencyProvider.Dependencies) { if (!root.Projects.Any(p => p.Name == libraryDescription.Identity.Name)) { var bundleProject = new BundleProject( dependencyContext.ProjectReferenceDependencyProvider, dependencyContext.ProjectResolver, libraryDescription); if (bundleProject.Name == project.Name) { bundleProject.WwwRoot = _options.WwwRoot; bundleProject.WwwRootOut = _options.WwwRootOut; } root.Projects.Add(bundleProject); } } } NativeImageGenerator nativeImageGenerator = null; if (_options.Native) { nativeImageGenerator = NativeImageGenerator.Create(_options, root, frameworkContexts.Values); if (nativeImageGenerator == null) { _options.Reports.Error.WriteLine("Fail to initiate native image generation process.".Red()); return(false); } } root.Emit(); if (!ScriptExecutor.Execute(project, "postbundle", getVariable)) { _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage); return(false); } if (_options.Native && !nativeImageGenerator.BuildNativeImages(root)) { _options.Reports.Error.WriteLine("Native image generation failed."); return(false); } sw.Stop(); _options.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed); return(!anyUnresolvedDependency); }
private void GenerateWebConfigFileForWwwRootOut(BundleRoot root, Runtime.Project project, string wwwRootOutPath) { // Generate web.config for public app folder var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config"); var wwwRootSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot); var webConfigFilePath = Path.Combine(wwwRootSourcePath, "web.config"); XDocument xDoc; if (File.Exists(webConfigFilePath)) { xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath)); } else { xDoc = new XDocument(); } if (xDoc.Root == null) { xDoc.Add(new XElement("configuration")); } if (xDoc.Root.Name != "configuration") { throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file"); } var appSettingsElement = GetOrAddElement(parent: xDoc.Root, name: "appSettings"); var relativePackagesPath = PathUtility.GetRelativePath(wwwRootOutWebConfigFilePath, root.TargetPackagesPath); var defaultRuntime = root.Runtimes.FirstOrDefault(); var keyValuePairs = new Dictionary<string, string>() { { Runtime.Constants.WebConfigKpmPackagePath, relativePackagesPath}, { Runtime.Constants.WebConfigBootstrapperVersion, GetBootstrapperVersion(root)}, { Runtime.Constants.WebConfigRuntimePath, relativePackagesPath}, { Runtime.Constants.WebConfigRuntimeVersion, GetRuntimeVersion(defaultRuntime)}, { Runtime.Constants.WebConfigRuntimeFlavor, GetRuntimeFlavor(defaultRuntime)}, { Runtime.Constants.WebConfigRuntimeAppBase, _applicationBase}, }; foreach (var pair in keyValuePairs) { var addElement = appSettingsElement.Elements() .Where(x => x.Name == "add" && x.Attribute("key").Value == pair.Key) .SingleOrDefault(); if (addElement == null) { addElement = new XElement("add"); addElement.SetAttributeValue("key", pair.Key); appSettingsElement.Add(addElement); } addElement.SetAttributeValue("value", pair.Value); } var xmlWriterSettings = new XmlWriterSettings { Indent = true, ConformanceLevel = ConformanceLevel.Auto }; using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings)) { xDoc.WriteTo(xmlWriter); } }
private void CopyProject(BundleRoot root, Runtime.Project project, string targetPath, bool includeSource) { // A set of excluded files/directories used as a filter when doing copy var excludeSet = new HashSet<string>(project.BundleExcludeFiles, StringComparer.OrdinalIgnoreCase); var contentFiles = new HashSet<string>(project.ContentFiles, StringComparer.OrdinalIgnoreCase); // If a public folder is specified with 'webroot' or '--wwwroot', we ignore it when copying project files var wwwRootPath = string.Empty; if (!string.IsNullOrEmpty(WwwRoot)) { wwwRootPath = Path.Combine(project.ProjectDirectory, WwwRoot); wwwRootPath = PathUtility.EnsureTrailingSlash(wwwRootPath); } // If project root is used as value of '--wwwroot', we shouldn't exclude it when copying if (string.Equals(wwwRootPath, PathUtility.EnsureTrailingSlash(project.ProjectDirectory))) { wwwRootPath = string.Empty; } root.Operations.Copy(project.ProjectDirectory, targetPath, itemPath => { // If current file/folder is in the exclusion list, we don't copy it if (excludeSet.Contains(itemPath)) { return false; } // If current file is in the public folder, we don't copy it to destination project if (!string.IsNullOrEmpty(wwwRootPath) && itemPath.StartsWith(wwwRootPath)) { return false; } // The full path of target generated by copy operation should also be excluded var targetFullPath = itemPath.Replace(project.ProjectDirectory, TargetPath); excludeSet.Add(targetFullPath); if (includeSource) { return true; } if (Directory.Exists(itemPath)) { return true; } return contentFiles.Contains(itemPath); }); }