Open mwpowellhtx opened 5 years ago
@rainersigwald Any ideas on this one, good sir?
Short of having to do more bookkeeping on the version(s) involved, that is. I could open that can of worms in my tool, but I would rather simply trigger on a single build event for the build as a whole instead of for each of the targets involved during the build.
That or separate my single multi-targeted project file to several individually targets project files, each of which having its own uniquely tracked version numbers, but this does not seem like an especially great workaround, to me. ... Kind of defeats the purpose of it being multi-targeted in the first place; never mind the packaging headache that would occur.
Maybe you would find the buildMultiTargeting
folder useful? I can't find official documentation at all, but these links might help (Ctrl+F for buildMultiTargeting
on each page):
https://natemcmaster.com/blog/2017/07/05/msbuild-task-in-nuget/#step-4---shipping-your-task-in-a-nuget-package https://oren.codes/2017/01/04/multi-targeting-the-world-a-single-project-to-rule-them-all/#how-it-works
@jnm2 Will have to look into that a bit further, thank you for the tidbits.
I'm going to answer the question you're asking, but I'm a bit concerned based on your description of the symptoms that it may not be the root cause of your problem, so we may have to follow up again.
If you're not already delivering this target in a NuGet package, consider making the target conditional.
The condition isn't trivial, because there are a few interesting cases:
TargetFramework
.Common.targets provides $(IsCrossTargetingBuild)
for the third case, but we don't have a single propery for "this project multitargets". We generally use:
'$(TargetFrameworks)' == ''
'$(TargetFrameworks)' != '' and '$(TargetFramework)' == ''
'$(TargetFrameworks)' != '' and '$(TargetFramework)' != ''
see the definition of IsCrossTargetingBuild
itself:
If you know the project multitargets and want the smallest possible thing, you can use Condition=" '$(TargetFramework)' == '' "
.
@rainersigwald I'm not sure I understand, so this will yield a single overall build, that in turn would trigger my version bump once and only once? If I understand correctly, would yield multiple subordinate packages organized by the parent package?
For reference, currently the bump tasking is invoked BeforeTargets="BeforeBuild"
.
Thanks for linking to your code. I see now that you're providing a NuGet package, so the right thing to do is to use the buildCrossTargeting
folder, which handles the conditionality for you (NuGet imports it only for the "outer" build). @jnm2 was right on target.
so this will yield a single overall build
I don't think I understand this. "Build" is used for a lot of things (formally and informally) in MSBuild-land; can you ask this question without using that word, please?
If I understand correctly, would yield multiple subordinate packages organized by the parent package?
I don't understand this question, can you rephrase?
@rainersigwald Sounds like buildCrossTargeting
is the right path for me to investigate. Basically, I want to bump once and only once; that is, once regardless whether the subscribing project is single- or multi-targeting.
@rainersigwald So the current target would work in the single-targeting use case under the, Condition="'$(IsCrossTargetingBuild)' != 'true'"
. However, what would the analog outer loop target be when Condition="'$(IsCrossTargetingBuild)' == 'true'"
?
@rainersigwald I've dug into these a bit and I still do not see anything that jumps out at me as being a once and only once cross targets analog to the BeforeBuild
target. Can you confirm? Better yet, inform me as to what those target(s) might be? With the goal being a resilient version bumping strategy that bumps once and only once, regardless of whether single- or multi-targeting.
@rainersigwald Perhaps we could trigger on GetAllRuntimeIdentifiers
at a level or two prior to even the Build
targets?
You could use BeforeTargets="DispatchToInnerBuilds"
but we should expose BeforeBuild
in that case too. Updating the bug title.
@rainersigwald Good name for it. Agreed; is there anything we can do in the near term? At the moment I basically have bumping disabled, bypassing, my multi-target projects. Not a great workaround, manually bumping, but better than if we bump multiple times over a single outer build.
Edit: So if I take that correctly, that is a refactor of BeforeBuild
to the outer build scope?
Edit: Or at least identifying a CrossTargetBeforeBuild
target name.
Attached build events, logged via messaging.
vs-ide-msbuild-event-messages.txt
Along the lines of:
<Target Name="PreBeforeBuild" BeforeTargets="BeforeBuild">
<Message Text="PreBeforeBuild" Importance="high" />
</Target>
<Target Name="PreDispatchToInnerBuilds" BeforeTargets="DispatchToInnerBuilds">
<Message Text="PreDispatchToInnerBuilds" Importance="high" />
</Target>
That could work, gauging by the order of logged events.
@rainersigwald This is a qualified might work... Apparently IsCrossTargetingBuild
is never defined when we meet the BeforeBuild
target, regardless whether the project was a multi-target build. So my question shifts to a slightly different one, is there a target preceding BeforeBuild for single-target builds? And/or a better indicator, perhaps we need to test for existence of files, that sort of thing. Kind of a kludge workaround, but I do not know of a better way to signal when this happens.
Log attached, one single targeted, one multi-targeted, lines of interest highlighted with ^
s:
One approach seems to have some promise, involving TargetFrameworks
:
@rainersigwald As I mentioned a qualified might work. Another key property when DispatchToInnerBuilds
occurs as the absence of ProjectPath
. This is also key for my targets. However, MSBuildProjectFullPath
does appear to exist, so we may be able to leverage that property instead.
Edit: however, this also raises a bit of a question for me, does this mean that key Properties or Items would not be available during the outer build? This is also an essential part of my bump versions strategy.
@rainersigwald This is turning into a really curious case, indeed. I think that the inner/outer loop issue is part of it, but I do not think that is the entirety of the issue, having some difficulty pinpointing the other variable(s) influencing the apparent lack of a version bump going on.
I've reported a couple of key metrics if it helps. Continuing to dig into it further:
msbuild-bumpassemblyversions-not-working.txt
Edit: It is almost as though Directory.Build.props, when my bump targets would be included, is being partially, if not completely, ignored, at that step in the outer build loop. Otherwise, version bumping is working just fine for single-targeted projects.
My workaround seems to be along these lines, at the project level:
<Import Project="..\packages\bumpassemblyversions\$(BumpAssemblyVersionsVersion)\build\BumpAssemblyVersions.targets" Condition="'$(TargetFrameworks)' != '' And Exists('..\packages\BumpAssemblyVersions\$(BumpAssemblyVersionsVersion)\build\BumpAssemblyVersions.targets')" />
Where:
<BumpAssemblyVersionsVersion>1.3.0</BumpAssemblyVersionsVersion>
Steps to reproduce
I have a Bump Assembly Versions project which to this point has worked fine for single target projects. However, in multi-target projects, I am noticing that I may see a +N or sometimes a +N-1 increment, depending on the bump instructions, i.e. like one of the interior platforms unwound its build asynchronously last. This is incorrect, I only want there to be at most a +1 when there is an increment involved. So... Is there a target I can trigger against that represents the overall build and not each target framework?