Specifing different versions of the same Nuget package in one .csproj file
If you are developing AutoCAD plugins, you may need to build different versions of your project for different AutoCAD versions. In this blog post, we will explore how to design a csproj file that allows building different versions of an AutoCAD plugin for different AutoCAD versions from one .csproj
file (or .vbproj
file, respectively).
The problem with building different versions of an AutoCAD plugin
Each version of AutoCAD comes with its own API version, so plugins that are built for one version of AutoCAD may not be compatible with another version. In this case, you need to build separate versions of your plugin for each AutoCAD version that you want to support. However, building separate versions of your plugin means having separate .csproj
files which share the same code base but use different AutoCAD APIs. This is a maintenance hell as the number of versions grows.
The solution: using different build configurations to specify AutoCAD versions
One way to solve this problem is to use different build configurations in your .csproj
file to specify the AutoCAD version for which you are building the plugin. You can create different build configurations for each AutoCAD version, and then use the Choose
element to specify different options based on the build configuration.
Here's part of the .csproj
file from Linq2Acad:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug_2022|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug_2022\</OutputPath>
<DefineConstants>DEBUG;TRACE;AutoCAD_2022</DefineConstants>
<DocumentationFile>bin\Debug_2022\Linq2Acad.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug_2023|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug_2023\</OutputPath>
<DefineConstants>DEBUG;TRACE;AutoCAD_2023</DefineConstants>
<DocumentationFile>bin\Debug_2023\Linq2Acad.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_2022|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release_2022\</OutputPath>
<DefineConstants>TRACE;AutoCAD_2022</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>1591</NoWarn>
<DocumentationFile>bin\Release_2022\Linq2Acad.xml</DocumentationFile>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_2023|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release_2023\</OutputPath>
<DefineConstants>TRACE;AutoCAD_2023</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<NoWarn>1591</NoWarn>
<DocumentationFile>bin\Release_2023\Linq2Acad.xml</DocumentationFile>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<!-- Reference items -->
</ItemGroup>
<ItemGroup>
<!-- Compile items -->
</ItemGroup>
<Choose>
<When Condition="$(DefineConstants.Contains('AutoCAD_2022'))">
<ItemGroup>
<PackageReference Include="AutoCAD.NET.Core">
<Version>24.1.51000</Version>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
</When>
<When Condition="$(DefineConstants.Contains('AutoCAD_2023'))">
<ItemGroup>
<PackageReference Include="AutoCAD.NET.Core">
<Version>24.2.0</Version>
<ExcludeAssets>runtime</ExcludeAssets>
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
In this example, we have defined four different build configurations, Debug_2022
, Debug_2023
, Release_2022
and Release_2023
, for AutoCAD 2022 and AutoCAD 2023, respectively. Each build configuration defines a constant AutoCAD_XXXX
to specify the AutoCAD version. As an example, for AutoCAD 2022 we defined Debug_2022
and Release_2022
which both define the constant AutoCAD_2022
.
The important part is the Choose
element in line 58. Each When
-branch of the Choose
element checks for the existence of a constant and selects the Nuget package if the condition is true.
As a result, when you build the project with the Debug_2022
configuration, the project will reference the AutoCAD 2022 API, and when you build the project with the Debug_2023
configuration, the project will reference the AutoCAD 2023 API.