Merge pull request #1272 from cdmihai/cdmihai/noDependencies
Add --no-dependency flag to build
This commit is contained in:
commit
82bbd22d46
7 changed files with 109 additions and 47 deletions
|
@ -8,15 +8,18 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
internal class BuilderCommandApp : CompilerCommandApp
|
internal class BuilderCommandApp : CompilerCommandApp
|
||||||
{
|
{
|
||||||
public const string BuildProfileFlag = "--build-profile";
|
public const string BuildProfileFlag = "--build-profile";
|
||||||
public const string ForceUnsafeFlag = "--no-incremental";
|
public const string NoIncrementalFlag = "--no-incremental";
|
||||||
|
public const string NoDependenciesFlag = "--no-dependencies";
|
||||||
|
|
||||||
public bool BuildProfileValue => OptionHasValue(BuildProfileFlag);
|
public bool ShouldPrintIncrementalPreconditions => OptionHasValue(BuildProfileFlag);
|
||||||
public bool ForceUnsafeValue => OptionHasValue(ForceUnsafeFlag);
|
public bool ShouldNotUseIncrementality => OptionHasValue(NoIncrementalFlag);
|
||||||
|
public bool ShouldSkipDependencies => OptionHasValue(NoDependenciesFlag);
|
||||||
|
|
||||||
public BuilderCommandApp(string name, string fullName, string description) : base(name, fullName, description)
|
public BuilderCommandApp(string name, string fullName, string description) : base(name, fullName, description)
|
||||||
{
|
{
|
||||||
AddNoValueOption(BuildProfileFlag, "Set this flag to print the incremental safety checks that prevent incremental compilation");
|
AddNoValueOption(BuildProfileFlag, "Set this flag to print the incremental safety checks that prevent incremental compilation");
|
||||||
AddNoValueOption(ForceUnsafeFlag, "Set this flag to turn off incremental build");
|
AddNoValueOption(NoIncrementalFlag, "Set this flag to turn off incremental build");
|
||||||
|
AddNoValueOption(NoDependenciesFlag, "Set this flag to ignore project to project references and only build the root project");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,9 +23,9 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
public static readonly string[] KnownCompilers = { "csc", "vbc", "fsc" };
|
public static readonly string[] KnownCompilers = { "csc", "vbc", "fsc" };
|
||||||
|
|
||||||
private readonly ProjectContext _rootProject;
|
private readonly ProjectContext _rootProject;
|
||||||
|
private readonly ProjectDependenciesFacade _rootProjectDependencies;
|
||||||
private readonly BuilderCommandApp _args;
|
private readonly BuilderCommandApp _args;
|
||||||
private readonly IncrementalPreconditions _preconditions;
|
private readonly IncrementalPreconditions _preconditions;
|
||||||
private readonly ProjectDependenciesFacade _dependencies;
|
|
||||||
|
|
||||||
public bool IsSafeForIncrementalCompilation => !_preconditions.PreconditionsDetected();
|
public bool IsSafeForIncrementalCompilation => !_preconditions.PreconditionsDetected();
|
||||||
|
|
||||||
|
@ -37,11 +37,8 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
// and then reasoning which ones to get from args and which ones from fields.
|
// and then reasoning which ones to get from args and which ones from fields.
|
||||||
_args = (BuilderCommandApp)args.ShallowCopy();
|
_args = (BuilderCommandApp)args.ShallowCopy();
|
||||||
|
|
||||||
_args.OutputValue = _args.OutputValue;
|
|
||||||
_args.BuildBasePathValue = _args.BuildBasePathValue;
|
|
||||||
|
|
||||||
// Set up dependencies
|
// Set up dependencies
|
||||||
_dependencies = new ProjectDependenciesFacade(_rootProject, _args.ConfigValue);
|
_rootProjectDependencies = new ProjectDependenciesFacade(_rootProject, _args.ConfigValue);
|
||||||
|
|
||||||
// gather preconditions
|
// gather preconditions
|
||||||
_preconditions = GatherIncrementalPreconditions();
|
_preconditions = GatherIncrementalPreconditions();
|
||||||
|
@ -51,17 +48,36 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
{
|
{
|
||||||
CreateOutputDirectories();
|
CreateOutputDirectories();
|
||||||
|
|
||||||
// compile dependencies
|
return CompileDendencies(incremental) && CompileRootProject(incremental);
|
||||||
foreach (var dependency in Sort(_dependencies.ProjectDependenciesWithSources))
|
}
|
||||||
{
|
|
||||||
if (incremental)
|
|
||||||
{
|
|
||||||
var dependencyProjectContext = ProjectContext.Create(dependency.Path, dependency.Framework, new[] { _rootProject.RuntimeIdentifier });
|
|
||||||
|
|
||||||
if (!NeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue)))
|
private bool CompileRootProject(bool incremental)
|
||||||
{
|
{
|
||||||
continue;
|
if (incremental && !NeedsRebuilding(_rootProject, _rootProjectDependencies))
|
||||||
}
|
{
|
||||||
|
// todo: what if the previous build had errors / warnings and nothing changed? Need to propagate them in case of incremental
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var success = InvokeCompileOnRootProject();
|
||||||
|
|
||||||
|
PrintSummary(success);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CompileDendencies(bool incremental)
|
||||||
|
{
|
||||||
|
if (_args.ShouldSkipDependencies)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dependency in Sort(_rootProjectDependencies.ProjectDependenciesWithSources))
|
||||||
|
{
|
||||||
|
if (incremental && !DependencyNeedsRebuilding(dependency))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!InvokeCompileOnDependency(dependency))
|
if (!InvokeCompileOnDependency(dependency))
|
||||||
|
@ -70,28 +86,18 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incremental && !NeedsRebuilding(_rootProject, _dependencies))
|
return true;
|
||||||
{
|
}
|
||||||
// todo: what if the previous build had errors / warnings and nothing changed? Need to propagate them in case of incremental
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compile project
|
private bool DependencyNeedsRebuilding(ProjectDescription dependency)
|
||||||
var success = InvokeCompileOnRootProject();
|
{
|
||||||
|
var dependencyProjectContext = ProjectContext.Create(dependency.Path, dependency.Framework, new[] { _rootProject.RuntimeIdentifier });
|
||||||
PrintSummary(success);
|
return NeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue));
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies)
|
private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies)
|
||||||
{
|
{
|
||||||
return NeedsRebuilding(project, dependencies, _args.BuildBasePathValue);
|
var compilerIO = GetCompileIO(project, _args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue, dependencies, project == _rootProject);
|
||||||
}
|
|
||||||
|
|
||||||
private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies, string baseBuildPath)
|
|
||||||
{
|
|
||||||
var compilerIO = GetCompileIO(project, _args.ConfigValue, baseBuildPath, _args.OutputValue, dependencies, project == _rootProject);
|
|
||||||
|
|
||||||
// rebuild if empty inputs / outputs
|
// rebuild if empty inputs / outputs
|
||||||
if (!(compilerIO.Outputs.Any() && compilerIO.Inputs.Any()))
|
if (!(compilerIO.Outputs.Any() && compilerIO.Inputs.Any()))
|
||||||
|
@ -195,9 +201,9 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
|
|
||||||
private IncrementalPreconditions GatherIncrementalPreconditions()
|
private IncrementalPreconditions GatherIncrementalPreconditions()
|
||||||
{
|
{
|
||||||
var preconditions = new IncrementalPreconditions(_args.BuildProfileValue);
|
var preconditions = new IncrementalPreconditions(_args.ShouldPrintIncrementalPreconditions);
|
||||||
|
|
||||||
if (_args.ForceUnsafeValue)
|
if (_args.ShouldNotUseIncrementality)
|
||||||
{
|
{
|
||||||
preconditions.AddForceUnsafePrecondition();
|
preconditions.AddForceUnsafePrecondition();
|
||||||
}
|
}
|
||||||
|
@ -217,11 +223,16 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
// check the entire project tree that needs to be compiled, duplicated for each framework
|
// check the entire project tree that needs to be compiled, duplicated for each framework
|
||||||
private List<ProjectContext> GetProjectsToCheck()
|
private List<ProjectContext> GetProjectsToCheck()
|
||||||
{
|
{
|
||||||
|
if (_args.ShouldSkipDependencies)
|
||||||
|
{
|
||||||
|
return new List<ProjectContext>(1) { _rootProject };
|
||||||
|
}
|
||||||
|
|
||||||
// include initial root project
|
// include initial root project
|
||||||
var contextsToCheck = new List<ProjectContext>(1 + _dependencies.ProjectDependenciesWithSources.Count) { _rootProject };
|
var contextsToCheck = new List<ProjectContext>(1 + _rootProjectDependencies.ProjectDependenciesWithSources.Count) { _rootProject };
|
||||||
|
|
||||||
// convert ProjectDescription to ProjectContext
|
// convert ProjectDescription to ProjectContext
|
||||||
var dependencyContexts = _dependencies.ProjectDependenciesWithSources.Select
|
var dependencyContexts = _rootProjectDependencies.ProjectDependenciesWithSources.Select
|
||||||
(keyValuePair => ProjectContext.Create(keyValuePair.Value.Path, keyValuePair.Value.Framework));
|
(keyValuePair => ProjectContext.Create(keyValuePair.Value.Path, keyValuePair.Value.Framework));
|
||||||
|
|
||||||
contextsToCheck.AddRange(dependencyContexts);
|
contextsToCheck.AddRange(dependencyContexts);
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
|
|
||||||
public void AddForceUnsafePrecondition()
|
public void AddForceUnsafePrecondition()
|
||||||
{
|
{
|
||||||
_preconditions.Add($"[Forced Unsafe] The build was marked as unsafe. Remove the {BuilderCommandApp.ForceUnsafeFlag} flag to enable incremental compilation");
|
_preconditions.Add($"[Forced Unsafe] The build was marked as unsafe. Remove the {BuilderCommandApp.NoIncrementalFlag} flag to enable incremental compilation");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PreconditionsDetected()
|
public bool PreconditionsDetected()
|
||||||
|
|
|
@ -33,3 +33,6 @@ Prints out the incremental safety checks that users need to address in order for
|
||||||
|
|
||||||
--no-incremental
|
--no-incremental
|
||||||
Marks the build as unsafe for incrementality. This turns off incremental compilation and forces a clean rebuild of the project dependency graph.
|
Marks the build as unsafe for incrementality. This turns off incremental compilation and forces a clean rebuild of the project dependency graph.
|
||||||
|
|
||||||
|
--no-dependencies
|
||||||
|
Ignore project to project references and only build the root project specified to build.
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
private string _cppCompilerFlags;
|
private string _cppCompilerFlags;
|
||||||
private bool _buildProfile;
|
private bool _buildProfile;
|
||||||
private bool _noIncremental;
|
private bool _noIncremental;
|
||||||
|
private bool _noDependencies;
|
||||||
|
|
||||||
private string OutputOption
|
private string OutputOption
|
||||||
{
|
{
|
||||||
|
@ -166,6 +167,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string NoDependencies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _noDependencies ?
|
||||||
|
"--no-dependencies" :
|
||||||
|
"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BuildCommand(
|
public BuildCommand(
|
||||||
string projectPath,
|
string projectPath,
|
||||||
string output="",
|
string output="",
|
||||||
|
@ -181,11 +192,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
bool nativeCppMode=false,
|
bool nativeCppMode=false,
|
||||||
string cppCompilerFlags="",
|
string cppCompilerFlags="",
|
||||||
bool buildProfile=true,
|
bool buildProfile=true,
|
||||||
bool noIncremental=false
|
bool noIncremental=false,
|
||||||
|
bool noDependencies=false
|
||||||
)
|
)
|
||||||
: base("dotnet")
|
: base("dotnet")
|
||||||
{
|
{
|
||||||
|
|
||||||
_projectPath = projectPath;
|
_projectPath = projectPath;
|
||||||
_project = ProjectReader.GetProject(projectPath);
|
_project = ProjectReader.GetProject(projectPath);
|
||||||
|
|
||||||
|
@ -203,6 +214,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
_cppCompilerFlags = cppCompilerFlags;
|
_cppCompilerFlags = cppCompilerFlags;
|
||||||
_buildProfile = buildProfile;
|
_buildProfile = buildProfile;
|
||||||
_noIncremental = noIncremental;
|
_noIncremental = noIncremental;
|
||||||
|
_noDependencies = noDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult Execute(string args = "")
|
public override CommandResult Execute(string args = "")
|
||||||
|
@ -226,7 +238,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
|
|
||||||
private string BuildArgs()
|
private string BuildArgs()
|
||||||
{
|
{
|
||||||
return $"{BuildProfile} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
@ -13,7 +14,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
{
|
{
|
||||||
public class ProjectToProjectDependenciesIncrementalTest : IncrementalTestBase
|
public class ProjectToProjectDependenciesIncrementalTest : IncrementalTestBase
|
||||||
{
|
{
|
||||||
private string[] _projects = new[] { "L0", "L11", "L12", "L21", "L22" };
|
private readonly string[] _projects = new[] { "L0", "L11", "L12", "L21", "L22" };
|
||||||
|
|
||||||
public ProjectToProjectDependenciesIncrementalTest() : base(
|
public ProjectToProjectDependenciesIncrementalTest() : base(
|
||||||
Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects", "TestProjectToProjectDependencies"),
|
Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects", "TestProjectToProjectDependencies"),
|
||||||
|
@ -48,6 +49,38 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
AssertRebuilt(result3, expectedRebuiltProjects);
|
AssertRebuilt(result3, expectedRebuiltProjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestNoDependencyFlag()
|
||||||
|
{
|
||||||
|
var dependencies = new[] { "L11", "L12", "L21", "L22" };
|
||||||
|
|
||||||
|
// first clean build; all projects required compilation
|
||||||
|
var result1 = BuildProject();
|
||||||
|
AssertRebuilt(result1, _projects);
|
||||||
|
|
||||||
|
// modify the source code of a leaf dependency
|
||||||
|
TouchSourcesOfProject("L22");
|
||||||
|
|
||||||
|
// second build with no dependencies and no incremental; only the root rebuilds
|
||||||
|
var result2 = BuildProject(noDependencies: true, noIncremental: true);
|
||||||
|
result2.Should().StdOutMatchPattern("Compiling.*L0.*");
|
||||||
|
|
||||||
|
AssertResultDoesNotContainStrings(result2, dependencies);
|
||||||
|
|
||||||
|
// third build with no dependencies but incremental; nothing rebuilds
|
||||||
|
var result3 = BuildProject(noDependencies: true);
|
||||||
|
result3.Should().HaveSkippedProjectCompilation("L0");
|
||||||
|
AssertResultDoesNotContainStrings(result3, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssertResultDoesNotContainStrings(CommandResult commandResult, string[] strings)
|
||||||
|
{
|
||||||
|
foreach (var s in strings)
|
||||||
|
{
|
||||||
|
commandResult.StdOut.Should().NotContain(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// compute A - B
|
// compute A - B
|
||||||
private T[] SetDifference<T>(T[] A, T[] B)
|
private T[] SetDifference<T>(T[] A, T[] B)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,11 +46,11 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
|
File.SetLastWriteTimeUtc(file, DateTime.UtcNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CommandResult BuildProject(bool noIncremental = false, bool expectBuildFailure = false)
|
protected CommandResult BuildProject(bool noDependencies = false, bool noIncremental = false, bool expectBuildFailure = false)
|
||||||
{
|
{
|
||||||
var mainProjectFile = GetProjectFile(MainProject);
|
var mainProjectFile = GetProjectFile(MainProject);
|
||||||
|
|
||||||
var buildCommand = new BuildCommand(mainProjectFile, output: GetBinRoot(), framework: "dnxcore50", noIncremental : noIncremental);
|
var buildCommand = new BuildCommand(mainProjectFile, output: GetBinRoot(), framework: "dnxcore50", noIncremental : noIncremental, noDependencies : noDependencies);
|
||||||
var result = buildCommand.ExecuteWithCapturedOutput();
|
var result = buildCommand.ExecuteWithCapturedOutput();
|
||||||
|
|
||||||
if (!expectBuildFailure)
|
if (!expectBuildFailure)
|
||||||
|
|
Loading…
Add table
Reference in a new issue