Simplify the MSBuild targets in dotnet-watch
Use CustomAfterMicrosoftCommonTargets instead of MSBuildProjectExtensionsPath. - No more need to write to obj/$(Project).g.dotnetwatch.targets - Works on project that have changed default file locations via BaseIntermediateOutputPath Simplify DotNetWatch targets - Condense to one targets file - Simplify dependency chain of targets - Build project references in a parallel
This commit is contained in:
parent
aa93ce9299
commit
3dd029a8b5
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
<!-- Binary compatiblity is not a goal for command-line tools. -->
|
||||
<EnableApiCheck>false</EnableApiCheck>
|
||||
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
|
||||
<BaseOutputPath>$(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\</BaseOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ namespace Microsoft.DotNet.Watcher
|
|||
internal class CommandLineOptions
|
||||
{
|
||||
public string Project { get; private set; }
|
||||
public string MSBuildProjectExtensionsPath { get; private set; }
|
||||
public bool IsHelp { get; private set; }
|
||||
public bool IsQuiet { get; private set; }
|
||||
public bool IsVerbose { get; private set; }
|
||||
|
|
@ -78,12 +77,6 @@ Examples:
|
|||
var optProjects = app.Option("-p|--project <PROJECT>", "The project to watch",
|
||||
CommandOptionType.SingleValue);
|
||||
|
||||
var optMSBuildProjectExtensionsPath = app.Option("--msbuildprojectextensionspath <PATH>",
|
||||
"The MSBuild project extensions path. Defaults to \"obj\".",
|
||||
CommandOptionType.SingleValue);
|
||||
// Hide from help text because this is an internal option that will hopefully go away when/if #244 is resolved.
|
||||
optMSBuildProjectExtensionsPath.ShowInHelpText = false;
|
||||
|
||||
var optQuiet = app.Option("-q|--quiet", "Suppresses all output except warnings and errors",
|
||||
CommandOptionType.NoValue);
|
||||
var optVerbose = app.VerboseOption();
|
||||
|
|
@ -113,7 +106,6 @@ Examples:
|
|||
return new CommandLineOptions
|
||||
{
|
||||
Project = optProjects.Value(),
|
||||
MSBuildProjectExtensionsPath = optMSBuildProjectExtensionsPath.Value(),
|
||||
IsQuiet = optQuiet.HasValue(),
|
||||
IsVerbose = optVerbose.HasValue(),
|
||||
RemainingArguments = app.RemainingArguments,
|
||||
|
|
|
|||
|
|
@ -17,21 +17,19 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
public class MsBuildFileSetFactory : IFileSetFactory
|
||||
{
|
||||
private const string TargetName = "GenerateWatchList";
|
||||
private const string ProjectExtensionFileExtension = ".dotnetwatch.g.targets";
|
||||
private const string WatchTargetsFileName = "DotNetWatchCommon.targets";
|
||||
private const string WatchTargetsFileName = "DotNetWatch.targets";
|
||||
private readonly IReporter _reporter;
|
||||
private readonly string _projectFile;
|
||||
private readonly string _projectExtensionsPath;
|
||||
private readonly string _watchTargetsDir;
|
||||
private readonly OutputSink _outputSink;
|
||||
private readonly ProcessRunner _processRunner;
|
||||
private readonly bool _waitOnError;
|
||||
private readonly IReadOnlyList<string> _buildFlags;
|
||||
|
||||
public MsBuildFileSetFactory(IReporter reporter,
|
||||
string projectFile,
|
||||
string msBuildProjectExtensionsPath,
|
||||
bool waitOnError)
|
||||
: this(reporter, projectFile, msBuildProjectExtensionsPath, new OutputSink())
|
||||
bool waitOnError,
|
||||
bool trace)
|
||||
: this(reporter, projectFile, new OutputSink(), trace)
|
||||
{
|
||||
_waitOnError = waitOnError;
|
||||
}
|
||||
|
|
@ -39,8 +37,8 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
// output sink is for testing
|
||||
internal MsBuildFileSetFactory(IReporter reporter,
|
||||
string projectFile,
|
||||
string msBuildProjectExtensionsPath,
|
||||
OutputSink outputSink)
|
||||
OutputSink outputSink,
|
||||
bool trace)
|
||||
{
|
||||
Ensure.NotNull(reporter, nameof(reporter));
|
||||
Ensure.NotNullOrEmpty(projectFile, nameof(projectFile));
|
||||
|
|
@ -48,29 +46,13 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
|
||||
_reporter = reporter;
|
||||
_projectFile = projectFile;
|
||||
_watchTargetsDir = FindWatchTargetsDir();
|
||||
_outputSink = outputSink;
|
||||
_processRunner = new ProcessRunner(reporter);
|
||||
|
||||
// default value for MSBuildProjectExtensionsPath is $(BaseIntermediateOutputPath), which defaults to 'obj/'.
|
||||
_projectExtensionsPath = string.IsNullOrEmpty(msBuildProjectExtensionsPath)
|
||||
? Path.Combine(Path.GetDirectoryName(_projectFile), "obj")
|
||||
: msBuildProjectExtensionsPath;
|
||||
_buildFlags = InitializeArgs(FindTargetsFile(), trace);
|
||||
}
|
||||
|
||||
internal List<string> BuildFlags { get; } = new List<string>
|
||||
{
|
||||
"/nologo",
|
||||
"/v:n",
|
||||
"/t:" + TargetName,
|
||||
"/p:DotNetWatchBuild=true", // extensibility point for users
|
||||
"/p:DesignTimeBuild=true", // don't do expensive things
|
||||
};
|
||||
|
||||
public async Task<IFileSet> CreateAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
EnsureInitialized();
|
||||
|
||||
var watchList = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
|
|
@ -91,9 +73,8 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
{
|
||||
"msbuild",
|
||||
_projectFile,
|
||||
$"/p:_DotNetWatchTargetsLocation={_watchTargetsDir}", // add our dotnet-watch targets
|
||||
$"/p:_DotNetWatchListFile={watchList}"
|
||||
}.Concat(BuildFlags),
|
||||
}.Concat(_buildFlags),
|
||||
OutputCapture = capture
|
||||
};
|
||||
|
||||
|
|
@ -162,29 +143,31 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
}
|
||||
}
|
||||
|
||||
// Ensures file exists in $(MSBuildProjectExtensionsPath)/$(MSBuildProjectFile).dotnetwatch.targets
|
||||
private void EnsureInitialized()
|
||||
private IReadOnlyList<string> InitializeArgs(string watchTargetsFile, bool trace)
|
||||
{
|
||||
// see https://github.com/Microsoft/msbuild/blob/bf9b21cc7869b96ea2289ff31f6aaa5e1d525a26/src/XMakeTasks/Microsoft.Common.targets#L127
|
||||
var projectExtensionFile = Path.Combine(_projectExtensionsPath,
|
||||
Path.GetFileName(_projectFile) + ProjectExtensionFileExtension);
|
||||
|
||||
if (!File.Exists(projectExtensionFile))
|
||||
var args = new List<string>
|
||||
{
|
||||
// ensure obj folder is available
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(projectExtensionFile));
|
||||
"/nologo",
|
||||
"/v:n",
|
||||
"/t:" + TargetName,
|
||||
"/p:DotNetWatchBuild=true", // extensibility point for users
|
||||
"/p:DesignTimeBuild=true", // don't do expensive things
|
||||
"/p:CustomAfterMicrosoftCommonTargets=" + watchTargetsFile,
|
||||
"/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + watchTargetsFile,
|
||||
};
|
||||
|
||||
using (var fileStream = new FileStream(projectExtensionFile, FileMode.Create))
|
||||
using (var assemblyStream = GetType().GetTypeInfo().Assembly.GetManifestResourceStream("dotnetwatch.targets"))
|
||||
{
|
||||
assemblyStream.CopyTo(fileStream);
|
||||
}
|
||||
if (trace)
|
||||
{
|
||||
// enables capturing markers to know which projects have been visited
|
||||
args.Add("/p:_DotNetWatchTraceOutput=true");
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
private string FindWatchTargetsDir()
|
||||
private string FindTargetsFile()
|
||||
{
|
||||
var assemblyDir = Path.GetDirectoryName(GetType().GetTypeInfo().Assembly.Location);
|
||||
var assemblyDir = Path.GetDirectoryName(typeof(MsBuildFileSetFactory).Assembly.Location);
|
||||
var searchPaths = new[]
|
||||
{
|
||||
AppContext.BaseDirectory,
|
||||
|
|
@ -194,8 +177,13 @@ namespace Microsoft.DotNet.Watcher.Internal
|
|||
Path.Combine(AppContext.BaseDirectory, "../../toolassets"), // relative to packaged deps.json
|
||||
};
|
||||
|
||||
var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).First(File.Exists);
|
||||
return Path.GetDirectoryName(targetPath);
|
||||
var targetPath = searchPaths.Select(p => Path.Combine(p, WatchTargetsFileName)).FirstOrDefault(File.Exists);
|
||||
if (targetPath == null)
|
||||
{
|
||||
_reporter.Error("Fatal error: could not find DotNetWatch.targets");
|
||||
return null;
|
||||
}
|
||||
return targetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\shared\**\*.cs" />
|
||||
<EmbeddedResource Include="dotnetwatch.targets" LogicalName="dotnetwatch.targets" />
|
||||
<None Include="prefercliruntime" Pack="true" PackagePath="\prefercliruntime" />
|
||||
<None Include="toolassets\*.targets" Pack="true" CopyToOutputDirectory="PreserveNewest" PackagePath="%(Identity)" />
|
||||
<Content Include="prefercliruntime" PackagePath="\prefercliruntime" />
|
||||
<Content Include="toolassets\DotNetWatch.targets" CopyToOutputDirectory="PreserveNewest" PackagePath="%(Identity)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -87,14 +87,12 @@ namespace Microsoft.DotNet.Watcher
|
|||
{
|
||||
return await ListFilesAsync(_reporter,
|
||||
options.Project,
|
||||
options.MSBuildProjectExtensionsPath,
|
||||
_cts.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await MainInternalAsync(_reporter,
|
||||
options.Project,
|
||||
options.MSBuildProjectExtensionsPath,
|
||||
options.RemainingArguments,
|
||||
_cts.Token);
|
||||
}
|
||||
|
|
@ -129,7 +127,6 @@ namespace Microsoft.DotNet.Watcher
|
|||
private async Task<int> MainInternalAsync(
|
||||
IReporter reporter,
|
||||
string project,
|
||||
string msbuildProjectExtensionsPath,
|
||||
ICollection<string> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
|
@ -147,8 +144,8 @@ namespace Microsoft.DotNet.Watcher
|
|||
|
||||
var fileSetFactory = new MsBuildFileSetFactory(reporter,
|
||||
projectFile,
|
||||
NormalizePath(msbuildProjectExtensionsPath),
|
||||
waitOnError: true);
|
||||
waitOnError: true,
|
||||
trace: false);
|
||||
var processInfo = new ProcessSpec
|
||||
{
|
||||
Executable = DotNetMuxer.MuxerPathOrDefault(),
|
||||
|
|
@ -174,7 +171,6 @@ namespace Microsoft.DotNet.Watcher
|
|||
private async Task<int> ListFilesAsync(
|
||||
IReporter reporter,
|
||||
string project,
|
||||
string msbuildProjectExtensionsPath,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// TODO multiple projects should be easy enough to add here
|
||||
|
|
@ -191,8 +187,8 @@ namespace Microsoft.DotNet.Watcher
|
|||
|
||||
var fileSetFactory = new MsBuildFileSetFactory(reporter,
|
||||
projectFile,
|
||||
NormalizePath(msbuildProjectExtensionsPath),
|
||||
waitOnError: false);
|
||||
waitOnError: false,
|
||||
trace: false);
|
||||
var files = await fileSetFactory.CreateAsync(cancellationToken);
|
||||
|
||||
if (files == null)
|
||||
|
|
@ -211,21 +207,6 @@ namespace Microsoft.DotNet.Watcher
|
|||
private static IReporter CreateReporter(bool verbose, bool quiet, IConsole console)
|
||||
=> new PrefixConsoleReporter(console, verbose || CliContext.IsGlobalVerbose(), quiet);
|
||||
|
||||
private string NormalizePath(string path)
|
||||
{
|
||||
if (path == null || Path.IsPathRooted(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return _workingDir;
|
||||
}
|
||||
|
||||
return Path.Combine(_workingDir, path);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_console.CancelKeyPress -= OnCancelKeyPress;
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
<!-- This file is autogenerated by dotnet-watch. -->
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_DotNetWatchTargetsFile Condition="'$(_DotNetWatchTargetsFile)' == ''">$(MSBuildThisFileFullPath)</_DotNetWatchTargetsFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(_DotNetWatchTargetsLocation)\DotNetWatchCommon.targets"
|
||||
Condition="Exists('$(_DotNetWatchTargetsLocation)\DotNetWatchCommon.targets')" />
|
||||
|
||||
<ImportGroup Condition="'$(TargetFramework)'==''">
|
||||
<Import Project="$(_DotNetWatchTargetsLocation)\DotNetWatchOuter.targets"
|
||||
Condition="Exists('$(_DotNetWatchTargetsLocation)\DotNetWatchOuter.targets')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(TargetFramework)'!=''">
|
||||
<Import Project="$(_DotNetWatchTargetsLocation)\DotNetWatchInner.targets"
|
||||
Condition="Exists('$(_DotNetWatchTargetsLocation)\DotNetWatchInner.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!--
|
||||
=========================================================================
|
||||
GenerateWatchList
|
||||
|
||||
Main target called by dotnet-watch. It gathers MSBuild items and writes
|
||||
them to a file.
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="GenerateWatchList"
|
||||
DependsOnTargets="_CollectWatchItems">
|
||||
<WriteLinesToFile Overwrite="true"
|
||||
File="$(_DotNetWatchListFile)"
|
||||
Lines="@(Watch -> '%(FullPath)')" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CollectWatchItems
|
||||
|
||||
Gathers all files to be watched.
|
||||
Returns: @(Watch)
|
||||
=========================================================================
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<_CollectWatchItemsDependsOn Condition=" '$(TargetFrameworks)' != '' AND '$(TargetFramework)' == '' ">
|
||||
_CollectWatchItemsPerFramework;
|
||||
</_CollectWatchItemsDependsOn>
|
||||
<_CollectWatchItemsDependsOn Condition=" '$(TargetFramework)' != '' ">
|
||||
_CoreCollectWatchItems;
|
||||
</_CollectWatchItemsDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CollectWatchItems" DependsOnTargets="$(_CollectWatchItemsDependsOn)" Returns="@(Watch)" />
|
||||
|
||||
<Target Name="_CollectWatchItemsPerFramework">
|
||||
<ItemGroup>
|
||||
<_TargetFramework Include="$(TargetFrameworks)" />
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
||||
Targets="_CoreCollectWatchItems"
|
||||
Properties="TargetFramework=%(_TargetFramework.Identity)">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="Watch" />
|
||||
</MSBuild>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CoreCollectWatchItems" Returns="@(Watch)">
|
||||
<!-- message used to debug -->
|
||||
<Message Importance="High" Text="Collecting watch items from '$(MSBuildProjectName)'" Condition="'$(_DotNetWatchTraceOutput)'=='true'" />
|
||||
|
||||
<Error Text="TargetFramework should be set" Condition="'$(TargetFramework)' == '' "/>
|
||||
|
||||
<ItemGroup>
|
||||
<Watch Include="%(Compile.FullPath)" Condition="'%(Compile.Watch)' != 'false'" />
|
||||
<Watch Include="%(EmbeddedResource.FullPath)" Condition="'%(EmbeddedResource.Watch)' != 'false'"/>
|
||||
<Watch Include="$(MSBuildProjectFullPath)" />
|
||||
<_WatchProjects Include="%(ProjectReference.Identity)" Condition="'%(ProjectReference.Watch)' != 'false'" />
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild Projects="@(_WatchProjects)"
|
||||
Targets="_CollectWatchItems"
|
||||
BuildInParallel="true">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="Watch" />
|
||||
</MSBuild>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<Target Name="_WriteGeneratedWatchList" >
|
||||
<WriteLinesToFile Overwrite="true"
|
||||
File="$(_DotNetWatchListFile)"
|
||||
Lines="@(Watch -> '%(FullPath)')" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CollectWatchItems
|
||||
|
||||
Invokes _CoreCollectWatchItems on each distinct project in _DotNetWatchProjects.
|
||||
|
||||
Returns: @(Watch)
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="_CollectWatchItems">
|
||||
<RemoveDuplicates Inputs="@(_DotNetWatchProjects)">
|
||||
<Output TaskParameter="Filtered" ItemName="_DotNetWatchProjectsFiltered" />
|
||||
</RemoveDuplicates>
|
||||
<MSBuild
|
||||
Targets="_CoreCollectWatchItems"
|
||||
Projects="%(_DotNetWatchProjectsFiltered.FullPath)">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="Watch"/>
|
||||
</MSBuild>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
GenerateWatchList
|
||||
|
||||
Main target called by dotnet-watch. This is the single-tfm version.
|
||||
For multi-tfm version, see the Outer.targets file for description of the
|
||||
design of this target.
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="GenerateWatchList"
|
||||
DependsOnTargets="_CollectWatchProjects;_CollectWatchItems;_WriteGeneratedWatchList" />
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CoreCollectWatchItems
|
||||
|
||||
Creates item group with default set of files to watch.
|
||||
|
||||
Returns: @(Watch)
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="_CoreCollectWatchItems" Returns="@(Watch)">
|
||||
<!-- message used to debug -->
|
||||
<Message Importance="High" Text="Collecting watch items from '$(MSBuildProjectName)'" Condition="'$(_DotNetWatchTraceOutput)'=='true'" />
|
||||
<ItemGroup>
|
||||
<Watch Include="@(Compile->'%(FullPath)')" Condition="'%(Compile.Watch)' != 'false'" />
|
||||
<Watch Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.Watch)' != 'false'"/>
|
||||
<Watch Include="$(MSBuildProjectFullPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CollectWatchProjects
|
||||
|
||||
Adds all ProjectReference items to _DotNetWatchProjects.
|
||||
Copies the project file extension file to all project references.
|
||||
Invokes '_CollectWatchProjects' on all referenced projects.
|
||||
|
||||
Returns: @(_DotNetWatchProjects)
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="_CollectWatchProjects"
|
||||
Returns="@(_DotNetWatchProjects)">
|
||||
<!-- message used to debug -->
|
||||
<Message Importance="High" Text="Collecting referenced projects from '$(MSBuildProjectName)'" Condition="'$(_DotNetWatchTraceOutput)'=='true'" />
|
||||
<ItemGroup>
|
||||
<_DotNetWatchProjects Include="@(ProjectReference->'%(FullPath)')" Condition="'%(ProjectReference.Watch)' != 'false'" />
|
||||
<_DotNetWatchImportsTargets Include="@(_DotNetWatchProjects->'%(RelativeDir)obj\%(FileName)%(Extension).dotnetwatch.targets')">
|
||||
<TargetsFile>$(_DotNetWatchTargetsFile)</TargetsFile>
|
||||
</_DotNetWatchImportsTargets>
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(_DotNetWatchImportsTargets->'%(TargetsFile)')"
|
||||
DestinationFiles="@(_DotNetWatchImportsTargets)"
|
||||
SkipUnchangedFiles="true" />
|
||||
|
||||
<MSBuild
|
||||
Targets="_CollectWatchProjects"
|
||||
Projects="%(_DotNetWatchProjects.FullPath)">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="_DotNetWatchProjects"/>
|
||||
</MSBuild>
|
||||
|
||||
<ItemGroup>
|
||||
<_DotNetWatchProjects Include="$(MSBuildProjectFullPath)"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
<Project
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
GenerateWatchList
|
||||
|
||||
Main target called by dotnet-watch. This is the cross-targetting version.
|
||||
For single-tfm, the 'GenerateWatchList' in Inner.targets is the main target.
|
||||
|
||||
Phase 1: _CollectWatchProjects:
|
||||
traverses the project-to-project graph to resolve all projects referenced.
|
||||
Phase 2: _CollectWatchItems:
|
||||
for each unique project file from phase 1, extracts all 'Watch' items and
|
||||
collects into a single item group. All values should be a fullpath.
|
||||
Phase 3: _WriteGeneratedWatchList:
|
||||
write all files to a file that can be read by dotnet-watch
|
||||
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="GenerateWatchList"
|
||||
DependsOnTargets="_CollectWatchProjects;_CollectWatchItems;_WriteGeneratedWatchList"
|
||||
/>
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CoreCollectWatchItems
|
||||
|
||||
Shim for cross-targetting builds to run _CoreCollectWatchItems for each target
|
||||
framework.
|
||||
|
||||
Returns: @(Watch)
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="_CoreCollectWatchItems"
|
||||
Returns="@(Watch)">
|
||||
<ItemGroup>
|
||||
<_TargetFramework Include="$(TargetFrameworks)" />
|
||||
</ItemGroup>
|
||||
<MSBuild Projects="$(MSBuildProjectFile)"
|
||||
Condition="'$(TargetFrameworks)' != '' "
|
||||
Targets="_CoreCollectWatchItems"
|
||||
Properties="TargetFramework=%(_TargetFramework.Identity)">
|
||||
<Output ItemName="Watch" TaskParameter="TargetOutputs" />
|
||||
</MSBuild>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
=========================================================================
|
||||
_CollectWatchProjects
|
||||
|
||||
Shim for cross-targetting builds to run _CollectWatchProjects for each target
|
||||
framework.
|
||||
|
||||
Returns: @(_DotNetWatchProjects)
|
||||
=========================================================================
|
||||
-->
|
||||
<Target Name="_CollectWatchProjects" Returns="@(_DotNetWatchProjects)">
|
||||
<ItemGroup>
|
||||
<_TargetFramework Include="$(TargetFrameworks)" />
|
||||
</ItemGroup>
|
||||
<MSBuild Projects="$(MSBuildProjectFile)"
|
||||
Condition="'$(TargetFrameworks)' != '' "
|
||||
Targets="_CollectWatchProjects"
|
||||
Properties="TargetFramework=%(_TargetFramework.Identity)">
|
||||
<Output ItemName="_DotNetWatchProjects" TaskParameter="TargetOutputs" />
|
||||
</MSBuild>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -41,11 +41,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|||
: base("KitchenSink", logger)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDefaultArgs()
|
||||
{
|
||||
return new[] { "--msbuildprojectextensionspath", ".net/obj", "run", "--" };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="..\Shared\**\*.cs" />
|
||||
<Content Include="TestProjects\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchInner.targets" Link="toolassets\DotNetWatchInner.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchOuter.targets" Link="toolassets\DotNetWatchOuter.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchCommon.targets" Link="toolassets\DotNetWatchCommon.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatch.targets" Link="toolassets\DotNetWatch.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|||
await PrepareAsync();
|
||||
}
|
||||
|
||||
var args = GetDefaultArgs().Concat(arguments);
|
||||
var args = new[] { "run", "--" }.Concat(arguments);
|
||||
Start(args, name);
|
||||
|
||||
// Make this timeout long because it depends much on the MSBuild compilation speed.
|
||||
|
|
@ -107,11 +107,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|||
await Process.GetOutputLineAsync(StartedMessage).TimeoutAfter(TimeSpan.FromMinutes(2));
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<string> GetDefaultArgs()
|
||||
{
|
||||
return new[] { "run", "--" };
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_logger?.WriteLine("Disposing WatchableApp");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<BaseIntermediateOutputPath>.net/obj</BaseIntermediateOutputPath>
|
||||
<BaseOutputPath>.net/bin</BaseOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
|
|||
|
||||
public static void EqualFileList(IEnumerable<string> expectedFiles, IEnumerable<string> actualFiles)
|
||||
{
|
||||
Func<string, string> normalize = p => p.Replace('\\', '/');
|
||||
string normalize(string p) => p.Replace('\\', '/');
|
||||
var expected = new HashSet<string>(expectedFiles.Select(normalize));
|
||||
var actual = new HashSet<string>(actualFiles.Where(p => !string.IsNullOrEmpty(p)).Select(normalize));
|
||||
if (!expected.SetEquals(actual))
|
||||
{
|
||||
throw new AssertActualExpectedException(
|
||||
expected: string.Join("\n", expected),
|
||||
actual: string.Join("\n", actual),
|
||||
expected: "\n" + string.Join("\n", expected),
|
||||
actual: "\n" + string.Join("\n", actual),
|
||||
userMessage: "File sets should be equal");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\**\*.cs" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchInner.targets" Link="toolassets\DotNetWatchInner.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchOuter.targets" Link="toolassets\DotNetWatchOuter.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatchCommon.targets" Link="toolassets\DotNetWatchCommon.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="..\..\src\Microsoft.DotNet.Watcher.Tools\toolassets\DotNetWatch.targets" Link="toolassets\DotNetWatch.targets" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -238,11 +238,7 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
|
|||
graph.Find("A").WithProjectReference(graph.Find("W"), watch: false);
|
||||
|
||||
var output = new OutputSink();
|
||||
var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate("A").Path, null, output)
|
||||
{
|
||||
// enables capturing markers to know which projects have been visited
|
||||
BuildFlags = { "/p:_DotNetWatchTraceOutput=true" }
|
||||
};
|
||||
var filesetFactory = new MsBuildFileSetFactory(_reporter, graph.GetOrCreate("A").Path, output, trace: true);
|
||||
|
||||
var fileset = await GetFileSet(filesetFactory);
|
||||
|
||||
|
|
@ -270,17 +266,10 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests
|
|||
Assert.Single(output.Current.Lines,
|
||||
line => line.Contains($"Collecting watch items from '{projectName}'"))
|
||||
);
|
||||
|
||||
// ensure each project is only visited once to collect project references
|
||||
Assert.All(includedProjects,
|
||||
projectName =>
|
||||
Assert.Single(output.Current.Lines,
|
||||
line => line.Contains($"Collecting referenced projects from '{projectName}'"))
|
||||
);
|
||||
}
|
||||
|
||||
private Task<IFileSet> GetFileSet(TemporaryCSharpProject target)
|
||||
=> GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, null, waitOnError: false));
|
||||
=> GetFileSet(new MsBuildFileSetFactory(_reporter, target.Path, waitOnError: false, trace: false));
|
||||
|
||||
private async Task<IFileSet> GetFileSet(MsBuildFileSetFactory filesetFactory)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue