Is it possible to have a UsingTask definition within a target?
My use-case is that I have a custom task within the same solution as the code that it is being applied to. Both co-evolve, so I'd like to have the custom task as a project reference of the projects that it's being applied to, and always use the latest build of the custom task for the consecutive projects of the same build. Is something like that possible, and of so how?
Thanks!
No, this isn't currently possible. UsingTasks are handled in pass 4 of the evaluator, before Targets are thought about and before the build itself (that is, target/task execution) even starts.
This is a reasonable feature request, though. I don't see a conceptual problem with doing it.
I can think of a couple of possible (untested) workarounds:
CodeTaskFactory to build your task. You can point to files on disk, and MSBuild itself will handle building the task assembly for you, so it's "always" up to date. Of course, this makes developing and debugging the task more difficult.Closing because this has workarounds and seems unlikely to come to the top of the feature-request list in the foreseeable future. If anyone would like to argue that it should, feel free to make a case.
@rainersigwald, this is something that could make source-build significantly simple for WPF on .NET Core.
I'm trying to puzzle out the best way to do markup compilation using (a) PresenationBuildTasks (PBT) that is built in our repo and (b) copy of Microsoft.WinFx.targets in our repo that we ship in the Sdk.
Ideally, we'd build our projects (that require Xaml compilation) as Net.Sdk projects, import Microsoft.WinFx.targets, and ProjectReference the WPF assemblies we need during build - so far, so good.
The trick is in having the full path to PresentationBuildTasks before we import Microsoft.winfx.targets, so that
If UsingTask were allowed within targets, I could write a preamble targets that runs before any of the PBT supplied targets, checks that
As is, I can try to make it all work using the existing infrastructure and the workarounds you've outlined here, but it is going to look very complicated.
I just replied to a similar question internally:
One option would be to add a target after ResolveProjectReferences and before the target that uses the task that copies the output of the task project (from the output of RPR) to a known location under the current project鈥檚 obj directory (something like $(IntermediateOutputPath)\TaskAssembly.dll), and use that in the UsingTask(probably by defining a property for both the destination of the copy and the using. This takes advantage of the fact that the assembly isn't loaded until a task in it is _used_, so the assembly doesn't need to exist at evaluation time.
assembly isn't loaded until a task in it is _used_
That's a great tip - thanks!
I just replied to a similar question internally:
One option would be to add a target after
ResolveProjectReferencesand before the target that uses the task that copies the output of the task project (from the output of RPR) to a known location under the current project鈥檚 obj directory (something like$(IntermediateOutputPath)\TaskAssembly.dll), and use that in theUsingTask(probably by defining a property for both the destination of the copy and the using. This takes advantage of the fact that the assembly isn't loaded until a task in it is _used_, so the assembly doesn't need to exist at evaluation time.
I'm just curious, how would that look like? And is this just an idea/theory, or does this really work?
@biohazard999
I was able to use this pattern successfully. See Pbt.targets for how we did it in WPF to use locally built PresentationBuildTasks.dll to run markup compilation for building WPF product assemblies like System.Windows.Controls.Ribbon.dll etc.
Most helpful comment
No, this isn't currently possible.
UsingTasks are handled in pass 4 of the evaluator, beforeTargetsare thought about and before the build itself (that is, target/task execution) even starts.This is a reasonable feature request, though. I don't see a conceptual problem with doing it.
I can think of a couple of possible (untested) workarounds:
CodeTaskFactoryto build your task. You can point to files on disk, and MSBuild itself will handle building the task assembly for you, so it's "always" up to date. Of course, this makes developing and debugging the task more difficult.