Imagine having a mathematics library, which provides some functionality optimized for IEEE754 number types. The code might have something along the lines of:
#if F16
global using Scalar = System.Half;
#elif F32
global using Scalar = System.Single;
#elif F32
global using Scalar = System.Double;
#endif
// ...
or
#if F32
public static float HighlyOptimizedMethod(float a, float b, float c) { ... };
#elif F64
public static double HighlyOptimizedMethod(double a, double b, double c) { ... };
#endif
I now define those preprocessor constants F16
, F32
, F64
in my .csproj
project file as follows:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- change the following for different precisions. -->
<!--<Scalar>F16</Scalar>-->
<!--<Scalar>F32</Scalar>-->
<Scalar>F64</Scalar>
<DefineConstants>$(DefineConstants);$(Scalar)</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName Condition="'$(Scalar)' != ''">mylibrary.$(Scalar)</AssemblyName>
<AssemblyName Condition="'$(Scalar)' == ''">mylibrary</AssemblyName>
...
</PropertyGroup>
</Project>
Is it possible to make VisualStudio/dotnet/MSBuild create the assemblies for all three configurations at the same time when building the project? i.e. would it be possible to run 'compile' and then have the following file list in the bin/
directory?
I tried fiddling around with something like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- change the following for different precisions. if all are commented out, every configuration will be built. -->
<!--<Scalar>F16</Scalar>-->
<!--<Scalar>F32</Scalar>-->
<Scalar>F64</Scalar>
<DefineConstants>$(DefineConstants);$(Scalar)</DefineConstants>
</PropertyGroup>
<Target Name="BuildOthers" BeforeTargets="CoreBuild" Condition="'$(Scalar)' == ''">
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F16" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F32" />
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F64" />
</Target>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
...
But it didn't get it to work. May someone be able to help me and/or point me into the right direction?
Thanks.
would it be possible to run 'compile' and then have the following file list in the bin/ directory?
Yes. You can check the following like this:
<PropertyGroup>
<Scalar>''</Scalar>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</PropertyGroup>
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F16" />
<Copy
SourceFiles="\obj\Debug\net8.0\mylibrary.F16.dll"
DestinationFolder="bin\$(Configuration)\Resources"
/>
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F32" />
<Copy
SourceFiles="\obj\Debug\net8.0\mylibrary.F32.dll"
DestinationFolder="bin\$(Configuration)\Resources"
/>
<MSBuild Projects="$(MSBuildProjectFile)" Properties="Configuration=$(Configuration);Scalar=F64" />
<Copy
SourceFiles="\obj\Debug\net8.0\mylibrary.F64.dll"
DestinationFolder="bin\$(Configuration)\Resources"
/>
</Target>
But it didn't get it to work(target BuildOthers)
Based on my test, i found the mylibrary.F12.dll
and mylibrary.F32.dll
are removed by target IncrementalClean
.
1.delte mylibrary.F12.dll
after generating mylibrary.F32.dll
2.delte mylibrary.F32.dll
after generating mylibrary.F64.dll
As we know, IncrementalClean
will remove files that were produced in a prior build. In this mode, it is not possible to have the three .dll file in bin
folder when run msbuild. To prevent files to be removed during incremental build, you can add <copy>
task to copy .dll
files to bin
folder.
Also you can try to disable incremental build. For more information, please read doc:--no-incremental
Besides, as the easiest way to achieve it ,you can try @Jonathan suggestion. Here is a similar ticket you can refer:
How to create multiple assets (dll) for one project with msbuild depend on Constants value?