From f9b559a60439610ae8ccdf13dd5b1cccd51621bf Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 8 Sep 2015 12:59:45 -0700 Subject: [PATCH] Enabling running scripts per configuration per framework Required to fix #887 --- .../Building/BuildManager.cs | 293 +++++++++--------- .../DnuPackTests.cs | 72 ++++- 2 files changed, 225 insertions(+), 140 deletions(-) diff --git a/src/Microsoft.Dnx.Tooling/Building/BuildManager.cs b/src/Microsoft.Dnx.Tooling/Building/BuildManager.cs index 258b06ccd..08a482028 100644 --- a/src/Microsoft.Dnx.Tooling/Building/BuildManager.cs +++ b/src/Microsoft.Dnx.Tooling/Building/BuildManager.cs @@ -6,11 +6,10 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.Versioning; using Microsoft.Dnx.Compilation; using Microsoft.Dnx.Compilation.Caching; -using Microsoft.Dnx.Compilation.FileSystem; using Microsoft.Dnx.Runtime; -using Microsoft.Dnx.Runtime.Compilation; using Microsoft.Dnx.Tooling.SourceControl; using Microsoft.Dnx.Tooling.Utils; using Microsoft.Framework.FileSystemGlobbing; @@ -127,192 +126,208 @@ private bool BuildInternal(string projectPath) return false; } - if (_buildOptions.GeneratePackages && - !ScriptExecutor.Execute(_currentProject, "prepack", GetScriptVariable)) + var success = true; + + var allDiagnostics = new List(); + + // Build all specified configurations + foreach (var configuration in configurations) { - LogError(ScriptExecutor.ErrorMessage); - return false; + success &= BuildConfiguration(baseOutputPath, frameworks, allDiagnostics, configuration); } - if (!ScriptExecutor.Execute(_currentProject, "prebuild", GetScriptVariable)) + sw.Stop(); + + if (projectDiagnostics.Any()) { - LogError(ScriptExecutor.ErrorMessage); - return false; - } + // Add a new line to separate the project diagnostics information from compilation diagnostics + _buildOptions.Reports.Information.WriteLine(); - var success = true; + projectDiagnostics.ForEach(d => LogWarning(d.FormattedMessage)); + } - var allDiagnostics = new List(); + allDiagnostics.AddRange(projectDiagnostics); + WriteSummary(allDiagnostics); + _buildOptions.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed); + return success; + } + private bool BuildConfiguration(string baseOutputPath, IEnumerable frameworks, List allDiagnostics, string configuration) + { PackageBuilder packageBuilder = null; PackageBuilder symbolPackageBuilder = null; InstallBuilder installBuilder = null; SourceBuilder sourceBuilder = null; - // Build all specified configurations - foreach (var configuration in configurations) + if (_buildOptions.GeneratePackages) { - if (_buildOptions.GeneratePackages) - { - // Create a new builder per configuration - packageBuilder = new PackageBuilder(); - symbolPackageBuilder = new PackageBuilder(); - InitializeBuilder(_currentProject, packageBuilder); - InitializeBuilder(_currentProject, symbolPackageBuilder); - installBuilder = new InstallBuilder(_currentProject, packageBuilder, _buildOptions.Reports); - sourceBuilder = new SourceBuilder(_currentProject, packageBuilder, _buildOptions.Reports); - } + // Create a new builder per configuration + packageBuilder = new PackageBuilder(); + symbolPackageBuilder = new PackageBuilder(); + InitializeBuilder(_currentProject, packageBuilder); + InitializeBuilder(_currentProject, symbolPackageBuilder); + installBuilder = new InstallBuilder(_currentProject, packageBuilder, _buildOptions.Reports); + sourceBuilder = new SourceBuilder(_currentProject, packageBuilder, _buildOptions.Reports); + } + + var success = true; - var configurationSuccess = true; + var outputPath = Path.Combine(baseOutputPath, configuration); - var outputPath = Path.Combine(baseOutputPath, configuration); + // Build all target frameworks a project supports + foreach (var targetFramework in frameworks) + { + _buildOptions.Reports.Information.WriteLine(); + _buildOptions.Reports.Information.WriteLine("Building {0} for {1}", + _currentProject.Name, targetFramework.ToString().Yellow().Bold()); - // Build all target frameworks a project supports - foreach (var targetFramework in frameworks) + if (!RunPreBuildScripts()) { - _buildOptions.Reports.Information.WriteLine(); - _buildOptions.Reports.Information.WriteLine("Building {0} for {1}", - _currentProject.Name, targetFramework.ToString().Yellow().Bold()); - - var diagnostics = new List(); + success = false; + continue; + } - var context = new BuildContext(_compilationEngine, - _currentProject, - targetFramework, - configuration, - outputPath); + var diagnostics = new List(); + var context = new BuildContext(_compilationEngine, + _currentProject, + targetFramework, + configuration, + outputPath); - context.Initialize(_buildOptions.Reports.Quiet); + context.Initialize(_buildOptions.Reports.Quiet); - if (context.Build(diagnostics)) + if (context.Build(diagnostics)) + { + if (_buildOptions.GeneratePackages) { - if (_buildOptions.GeneratePackages) - { - context.PopulateDependencies(packageBuilder); - context.AddLibs(packageBuilder, "*.dll"); - context.AddLibs(packageBuilder, "*.xml"); + context.PopulateDependencies(packageBuilder); + context.AddLibs(packageBuilder, "*.dll"); + context.AddLibs(packageBuilder, "*.xml"); - context.PopulateDependencies(symbolPackageBuilder); - context.AddLibs(symbolPackageBuilder, "*.*"); + context.PopulateDependencies(symbolPackageBuilder); + context.AddLibs(symbolPackageBuilder, "*.*"); - context.AddLibs(packageBuilder, "*.resources.dll", recursiveSearch: true); - } - } - else - { - configurationSuccess = false; + context.AddLibs(packageBuilder, "*.resources.dll", recursiveSearch: true); } - allDiagnostics.AddRange(diagnostics); - - WriteDiagnostics(diagnostics); + // Run post-build steps + success &= RunPostBuildScripts(); + } + else + { + success = false; } - success = success && configurationSuccess; + allDiagnostics.AddRange(diagnostics); + + WriteDiagnostics(diagnostics); + } - if (_buildOptions.GeneratePackages) + if (_buildOptions.GeneratePackages) + { + success = success && + // Generates the application package only if this is an application packages + installBuilder.Build(outputPath) && + sourceBuilder.Build(outputPath); + + if (success) { // Create a package per configuration - string nupkg = GetPackagePath(_currentProject, outputPath); - string symbolsNupkg = GetPackagePath(_currentProject, outputPath, symbols: true); + var nupkg = GetPackagePath(_currentProject, outputPath); + var symbolsNupkg = GetPackagePath(_currentProject, outputPath, symbols: true); - if (configurationSuccess) - { - // Generates the application package only if this is an application packages - configurationSuccess = installBuilder.Build(outputPath); - success = success && configurationSuccess; - } + return GeneratePackage(success, allDiagnostics, packageBuilder, symbolPackageBuilder, nupkg, symbolsNupkg); + } + } - if (configurationSuccess) - { - configurationSuccess = sourceBuilder.Build(outputPath); - success = success && configurationSuccess; - } + return success; + } - if (configurationSuccess) - { - var packDiagnostics = new List(); - foreach (var sharedFile in _currentProject.Files.SharedFiles) - { - var file = new PhysicalPackageFile(); - file.SourcePath = sharedFile; - file.TargetPath = String.Format(@"shared\{0}", Path.GetFileName(sharedFile)); - packageBuilder.Files.Add(file); - } + private bool RunPreBuildScripts() + { + if (_buildOptions.GeneratePackages && + !ScriptExecutor.Execute(_currentProject, "prepack", GetScriptVariable)) + { + LogError(ScriptExecutor.ErrorMessage); + return false; + } - var root = _currentProject.ProjectDirectory; + if (!ScriptExecutor.Execute(_currentProject, "prebuild", GetScriptVariable)) + { + LogError(ScriptExecutor.ErrorMessage); + return false; + } - if (_currentProject.Files.PackInclude != null && _currentProject.Files.PackInclude.Any()) - { - AddPackageFiles(_currentProject.ProjectDirectory, _currentProject.Files.PackInclude, packageBuilder, packDiagnostics); - } - success &= !packDiagnostics.HasErrors(); - allDiagnostics.AddRange(packDiagnostics); + return true; + } - foreach (var path in _currentProject.Files.SourceFiles) - { - var srcFile = new PhysicalPackageFile(); - srcFile.SourcePath = path; - srcFile.TargetPath = Path.Combine("src", PathUtility.GetRelativePath(root, path)); - symbolPackageBuilder.Files.Add(srcFile); - } - - // Write the packages as long as we're still in a success state. - if (success) - { - using (var fs = File.Create(nupkg)) - { - packageBuilder.Save(fs); - _buildOptions.Reports.Quiet.WriteLine("{0} -> {1}", _currentProject.Name, Path.GetFullPath(nupkg)); - } - - if (symbolPackageBuilder.Files.Any()) - { - using (var fs = File.Create(symbolsNupkg)) - { - symbolPackageBuilder.Save(fs); - _buildOptions.Reports.Quiet.WriteLine("{0} -> {1}", _currentProject.Name, Path.GetFullPath(symbolsNupkg)); - } - } - } - - WriteDiagnostics(packDiagnostics); - } - } + private bool RunPostBuildScripts() + { + if (!ScriptExecutor.Execute(_currentProject, "postbuild", GetScriptVariable)) + { + LogError(ScriptExecutor.ErrorMessage); + return false; } - // Run post-build steps - if (success) + if (_buildOptions.GeneratePackages && + !ScriptExecutor.Execute(_currentProject, "postpack", GetScriptVariable)) { - if (!ScriptExecutor.Execute(_currentProject, "postbuild", GetScriptVariable)) - { - LogError(ScriptExecutor.ErrorMessage); - success = false; - } + LogError(ScriptExecutor.ErrorMessage); + return false; + } - if (_buildOptions.GeneratePackages && - !ScriptExecutor.Execute(_currentProject, "postpack", GetScriptVariable)) - { - LogError(ScriptExecutor.ErrorMessage); - success = false; - } + return true; + } + + private bool GeneratePackage(bool success, List allDiagnostics, PackageBuilder packageBuilder, PackageBuilder symbolPackageBuilder, string nupkg, string symbolsNupkg) + { + var packDiagnostics = new List(); + foreach (var sharedFile in _currentProject.Files.SharedFiles) + { + var file = new PhysicalPackageFile(); + file.SourcePath = sharedFile; + file.TargetPath = String.Format(@"shared\{0}", Path.GetFileName(sharedFile)); + packageBuilder.Files.Add(file); } - sw.Stop(); + var root = _currentProject.ProjectDirectory; - if (projectDiagnostics.Any()) + if (_currentProject.Files.PackInclude != null && _currentProject.Files.PackInclude.Any()) { - // Add a new line to separate the project diagnostics information from compilation diagnostics - _buildOptions.Reports.Information.WriteLine(); + AddPackageFiles(_currentProject.ProjectDirectory, _currentProject.Files.PackInclude, packageBuilder, packDiagnostics); + } + success &= !packDiagnostics.HasErrors(); + allDiagnostics.AddRange(packDiagnostics); - projectDiagnostics.ForEach(d => LogWarning(d.FormattedMessage)); + foreach (var path in _currentProject.Files.SourceFiles) + { + var srcFile = new PhysicalPackageFile(); + srcFile.SourcePath = path; + srcFile.TargetPath = Path.Combine("src", PathUtility.GetRelativePath(root, path)); + symbolPackageBuilder.Files.Add(srcFile); } - allDiagnostics.AddRange(projectDiagnostics); - WriteSummary(allDiagnostics); + // Write the packages as long as we're still in a success state. + if (success) + { + using (var fs = File.Create(nupkg)) + { + packageBuilder.Save(fs); + _buildOptions.Reports.Quiet.WriteLine("{0} -> {1}", _currentProject.Name, Path.GetFullPath(nupkg)); + } - _buildOptions.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed); + if (symbolPackageBuilder.Files.Any()) + { + using (var fs = File.Create(symbolsNupkg)) + { + symbolPackageBuilder.Save(fs); + _buildOptions.Reports.Quiet.WriteLine("{0} -> {1}", _currentProject.Name, Path.GetFullPath(symbolsNupkg)); + } + } + } + + WriteDiagnostics(packDiagnostics); return success; } diff --git a/test/Microsoft.Dnx.Tooling.FunctionalTests/DnuPackTests.cs b/test/Microsoft.Dnx.Tooling.FunctionalTests/DnuPackTests.cs index 21b6494bb..9afdf2304 100644 --- a/test/Microsoft.Dnx.Tooling.FunctionalTests/DnuPackTests.cs +++ b/test/Microsoft.Dnx.Tooling.FunctionalTests/DnuPackTests.cs @@ -275,7 +275,7 @@ public void DnuPack_NormalizesVersionNumberWithNoBuildNumber(string flavor, stri arguments: string.Empty, workingDir: testEnv.ProjectPath); Assert.Equal(0, exitCode); - + Assert.True(File.Exists(Path.Combine(testEnv.ProjectPath, "bin", "Debug", $"{projectName}.1.0.0-beta.nupkg"))); Assert.True(File.Exists(Path.Combine(testEnv.ProjectPath, "bin", "Debug", $"{projectName}.1.0.0-beta.symbols.nupkg"))); } @@ -320,6 +320,76 @@ public void DnuPack_DoesNotExecutePostBuildScriptWhenBuildFails(string flavor, s } } + [Theory] + [MemberData(nameof(RuntimeComponents))] + public void DnuPack_ExecutesScriptsForEachConfigurationAndTargetFramework(string flavor, string os, string architecture) + { + var projectStructure = @"{ + '.': ['project.json'] +}"; + var runtimeHomeDir = TestUtils.GetRuntimeHomeDir(flavor, os, architecture); + + using (var testEnv = new DnuTestEnvironment(runtimeHomeDir, "TestProject")) + { + DirTree.CreateFromJson(projectStructure) + .WithFileContents("project.json", @"{ + ""version"": ""1.0-beta"", + ""frameworks"": { + ""dnx451"": {}, + ""dnxcore50"": { + ""dependencies"": { + ""System.Runtime"":""4.0.20-*"" + } + } + }, + ""scripts"": { + ""prebuild"": ""echo PREBUILD_SCRIPT_OUTPUT"", + ""prepack"": ""echo PREPACK_SCRIPT_OUTPUT"", + ""postbuild"": ""echo POSTBUILD_SCRIPT_OUTPUT"", + ""postpack"": ""echo POSTPACK_SCRIPT_OUTPUT"" + } +}") + .WriteTo(testEnv.ProjectPath); + + string stdOut, stdErr; + var exitCode = DnuTestUtils.ExecDnu( + runtimeHomeDir, + subcommand: "restore", + arguments: string.Empty, + workingDir: testEnv.ProjectPath); + Assert.Equal(0, exitCode); + + exitCode = DnuTestUtils.ExecDnu( + runtimeHomeDir, + "pack", + testEnv.ProjectPath + " --configuration Debug --configuration Release", + out stdOut, + out stdErr); + + Assert.Equal(0, exitCode); + Assert.Empty(stdErr); + + var idx = 0; + for (var i = 0; i < 4; i++) + { + idx = stdOut.IndexOf("PREPACK_SCRIPT_OUTPUT", idx); + Assert.True(idx >= 0); + idx = stdOut.IndexOf("PREBUILD_SCRIPT_OUTPUT", idx); + Assert.True(idx >= 0); + idx = stdOut.IndexOf("POSTBUILD_SCRIPT_OUTPUT", idx); + Assert.True(idx >= 0); + idx = stdOut.IndexOf("POSTPACK_SCRIPT_OUTPUT", idx); + Assert.True(idx >= 0); + idx += "POSTPACK_SCRIPT_OUTPUT".Length; + } + + Assert.Equal(-1, stdOut.IndexOf("PREPACK_SCRIPT_OUTPUT", idx)); + Assert.Equal(-1, stdOut.IndexOf("PREBUILD_SCRIPT_OUTPUT", idx)); + Assert.Equal(-1, stdOut.IndexOf("POSTBUILD_SCRIPT_OUTPUT", idx)); + Assert.Equal(-1, stdOut.IndexOf("POSTPACK_SCRIPT_OUTPUT", idx)); + } + } + [Theory] [MemberData(nameof(RuntimeComponents))] public void DnuPack_ShowUnresolvedDependencyWhenBuildFails(string flavor, string os, string architecture)