MSBuildSdks icon indicating copy to clipboard operation
MSBuildSdks copied to clipboard

Remove TargetFramework requirement from Microsoft.Build.NoTargets SDK

Open JVimes opened this issue 2 years ago • 8 comments

The NoTargets SDK seems to require TargetFramework. Without it I get:

MSB4044 The "ResolvePackageAssets" task was not given a value for the required parameter "TargetFramework".

Can that requirement be removed? The readme says NoTargets is "useful for utility projects that just copy files, build packages, or any other function where an assembly is not compiled". I have no need for a target framework in my case, and have dependency packages that should not be tied to a target framework either.

JVimes avatar Jun 12 '22 02:06 JVimes

The NoTargets SDK reuses a lot of the logic in Microsoft.NET.Sdk and just disables things related to compiling an assembly. Unfortunately that means that some things are required like TargetFramework. We could add a default value in Microsoft.Build.NoTargets but we were worried that if it was set to something like net6.0 you might get other errors about projects not being compatible and you wouldn't know what's going on since the value was set for you implicitly.

One way around this is to set a value for TargetFramework in a common import like Directory.Build.props:

<Project>
  <PropertyGroup>
    <!--
       Set TargetFramework to net6.0 for all projects using Microsoft.Build.NoTargets so that each project
       doesn't need to declare it
    -->
    <TargetFramework Condition="'$(UsingMicrosoftNoTargetsSdk)' == 'true'">net6.0</TargetFramework>
  </PropertyGroup>
</Project>

If we could get consensus on what the default TargetFramework should be for everyone, I'm open to adding to Microsoft.Build.NoTargets.

jeffkl avatar Jun 13 '22 18:06 jeffkl

Thanks for the backstory. Sounds like doing it more right would involve bigger changes and/or a "copy and modify" of the existing SDK.

But it would provide a couple benefits I could use:

  • Less confusion for devs reading my project file.
  • If my project builds a "tools only" or "build only" NuGet package (common use for NoTargets SDK), other "tools only" and "build only" dependency packages wouldn't end up under a target-framework group in my package's dependencies, thus avoiding unneeded "wrong target framework" errors for consumers. There may need to be a new per-dependency configuration here, not sure.
    • Current workaround is to move package info into a .nuspec file referenced via <NuspecFile> in the .cspproj. Since I need access to that info in MSBuild, have to pass all the package data to the .nuspec via <NuspecProperties>, which is ugly compared to the beautiful, clean way assembly-containing NuGet packages are defined nowadays.

It seems like there's good potential for the NoTargets SDK, but it could use more refinement to avoid confusion and hard-to-read workarounds.

JVimes avatar Jun 13 '22 19:06 JVimes

If we could get consensus on what the default TargetFramework should be for everyone, I'm open to adding to Microsoft.Build.NoTargets.

It seems like netstandard2.0 could be that - it's the most compatible. Besides some earlier netstandard versions, I suppose, but those seem to be way out of date by now.

If the target framework continues to be configurable by the user's project that uses NoTargets, then I think it would be acceptable to use netstandard2.0.

bddckr avatar Jun 14 '22 09:06 bddckr

Having a default target framework is different than not requiring one, such as the NuGet dependencies example in my comment.

I'd rather it be explicit than pretend it isn't a requirement but it is (just defaulted).

JVimes avatar Jun 14 '22 13:06 JVimes

@JVimes You can use <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking> for build tools that don't have any TargetFramework dependent references. It will modify the nuspec to remove the targets, allowing any consumer to reference your package. You still need a TargetFramework set in your package, but it essentially becomes a no-op.

kkirkfield avatar Dec 08 '22 04:12 kkirkfield

@JVimes You can use <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking> for build tools that don't have any TargetFramework dependent references. It will modify the nuspec to remove the targets, allowing any consumer to reference your package. You still need a TargetFramework set in your package, but it essentially becomes a no-op.

@kkirkfield, it also removes any dependency from the package.

Handwriting a nuspec is easy. I can even replace tokens using nuget.exe.

But managing dependencies using any tooling is not possible for handwriting a nuspec. NoTargets works with every tooling any other SDK works, including central package management.

Maybe what's missing is a Microsoft.Build.NuGet.Sdk SDK.

paulomorgado avatar Nov 04 '23 11:11 paulomorgado

Alternatively - there is an ambient property in the SDK called BundledNETCoreAppTargetFrameworkVersion that's set that could be a safe default for a TFM to use: <TargetFramework Condition="'$(TargetFramework)' == ''>net$(BundledNETCoreAppTargetFrameworkVersion)</TargetFramework>.

This property is set in the installer when creating the SDK bundles and has been around for several versions.

baronfel avatar Nov 10 '23 20:11 baronfel

But that still defines a TFM. Right, @baronfel?

paulomorgado avatar Nov 10 '23 21:11 paulomorgado