The idea is simple: I want to have a single project file, that can build multiple target frameworks and have references to different DLLs based on the framework used.
The issue that I am running into, is that when I select build on the project, it will build all frameworks defined in - but the .DLL referenced is newer than one of those target frameworks (which I need to build the same project with an older framework)
I only want to build a single framework automatically, then build the others manually.
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="Test">
<Target Name="Test">
<Message Importance="high" Text="-- Building $(MSBuildProjectFile), TF=$(TargetFramework), Config=$(Configuration), Version=$(MyCustomVersion) --" />
</Target>
<PropertyGroup>
<TargetFrameworks>net472;net48</TargetFrameworks>
<MyCustomVersion Condition="'$(MyCustomVersion)' == ''">2022</MyCustomVersion>
<OutputPath>bin\$(Configuration)\$(MyCustomVersion)\</OutputPath>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<PropertyGroup Condition="'$(MyCustomVersion)' == '2021' ">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);V2021</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(MyCustomVersion)' == '2021' ">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);V2021</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(MyCustomVersion)' == '2021' ">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);V2021</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(MyCustomVersion)' == '2022' ">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);V2022</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(MyCustomVersion)' == '2022' ">
<Reference Include="Some48API">
<HintPath>path\to\Some48API.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<Target Name="BuildOthers" BeforeTargets="DispatchToInnerBuilds" Condition="'$(MyCustomVersion)' == '2022'">
<Message Importance="high" Text="*** building 2019 ***" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);TargetFramework=net472;MyCustomVersion=2019" />
<Message Importance="high" Text="*** building 2020 ***" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);TargetFramework=net472;MyCustomVersion=2020" />
<Message Importance="high" Text="*** building 2021 ***" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);TargetFramework=net48;MyCustomVersion=2021" />
</Target>
</Project>
In the above project file, I have two TargetFrameworks: net472 and net48.
If I instead replace that with <TargetFramework>net48</TargetFramework>
(and modify BeforeTargets="DispatchToInnerBuilds" to BeforeTargets="PreBuildEvent"), I will get a compile error
0>C:\Program Files\dotnet\sdk\6.0.202\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(267,5): Error NETSDK1005 : Assets file 'C:\Users\me\source\repos\Solution1\ClassLibrary1\obj\project.assets.json' doesn't have a target for 'net472'. Ensure that restore has run and that you have included 'net472' in the TargetFrameworks for your project.
So it seems like I need to provide both but I don't want to build both of them without my own custom control over it...
This issue is inspired by TheBuildingCoder and specifically the RevitAPI dll files are net48 only for 2021/2022 - so I don't want to build net47 as I get compile errors due to broken reference...
I realize that what I was trying to do doesn't make a whole lot of sense... I want to prevent VS from building the other targets, only to manually build the other targets...
So instead of trying to prevent other targets getting built automatically, I can embrace that instead.
The changed project file looks like this (also more simplified):
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="Test">
<Target Name="Test">
<Message Importance="high" Text="-- Building $(MSBuildProjectFile), TF=$(TargetFramework), Config=$(Configuration), Version=$(MyCustomVersion) --" />
</Target>
<PropertyGroup>
<TargetFrameworks>net472;net48</TargetFrameworks>
<MyCustomVersion Condition="'$(MyCustomVersion)' == '' and '$(TargetFramework)' == 'net472'">2019</MyCustomVersion>
<MyCustomVersion Condition="'$(MyCustomVersion)' == '' and '$(TargetFramework)' == 'net48'">2022</MyCustomVersion>
<OutputPath>bin\$(Configuration)\$(MyCustomVersion)\</OutputPath>
<Configurations>Debug;Release</Configurations>
<IsPublishable>False</IsPublishable>
</PropertyGroup>
<PropertyGroup>
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);V$(MyCustomVersion)</DefineConstants>
</PropertyGroup>
<Target Name="BuildOthers" BeforeTargets="DispatchToInnerBuilds" Condition=" '$(MyCustomVersion)' == '' ">
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);TargetFramework=net472;MyCustomVersion=2020" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);TargetFramework=net48;MyCustomVersion=2021" />
</Target>
</Project>
The only downside is that it doesn't build them in preferable order:
1>-- Building ClassLibrary1.csproj, TF=, Config=Debug, Version= --
1>-- Building ClassLibrary1.csproj, TF=net472, Config=Debug, Version=2020 --
1>ClassLibrary1 -> C:\Users\me\source\repos\Solution1\ClassLibrary1\bin\Debug\2020\net472\ClassLibrary1.dll
1>-- Building ClassLibrary1.csproj, TF=net48, Config=Debug, Version=2021 --
1>ClassLibrary1 -> C:\Users\me\source\repos\Solution1\ClassLibrary1\bin\Debug\2021\net48\ClassLibrary1.dll
1>-- Building ClassLibrary1.csproj, TF=net472, Config=Debug, Version=2019 --
1>ClassLibrary1 -> C:\Users\me\source\repos\Solution1\ClassLibrary1\bin\Debug\2019\net472\ClassLibrary1.dll
1>-- Building ClassLibrary1.csproj, TF=net48, Config=Debug, Version=2022 --
1>ClassLibrary1 -> C:\Users\me\source\repos\Solution1\ClassLibrary1\bin\Debug\2022\net48\ClassLibrary1.dll
2020,2021,2019,2022 but that is a minor inconvenience and can probably be fixed with some shuffling