As part of my build process I want to run a dotnet tool before the compile.
I can add this section to my sdk project file:
<ItemGroup>
<PackageDownload Include="MyTool" Version="[1.0.1]" />
</ItemGroup>
Then the tool is downloaded and is available inside:
\Users\me\.nuget\packages\MyTool\1.0.1\tools\netcoreapp3.1\any\
I can then add a prebuild target like this:
<Target Name="PreBuild" BeforeTargets="CoreCompile">
<Exec Command="dotnet C:\Users\me\.nuget\packages\MyTool\1.0.1\tools\netcoreapp3.1\any\MyTool.dll <MyOptions> />
</Target>
This works, but obviously I do not want absolute references to my user profile (or version) in the path.
Is there a way to substitute path with an environment variable?
I have tried adding GeneratePathProperty="true"
to the PackageDownload but $(PkgMyTool) is undefined.
I also tried referencing the tool with <PackageReference>
but this fails due to SDK incompatibility. My Tool is netcore3.1 and this project is netstandard2.0.
As you learned, PackageDownload
doesn’t yet support GeneratePathProperty
. Here are a couple of workarounds you could try, though:
PackageReference
(not PackageDownload
) and use PrivateAssets
/ExcludeAssets
to control what happens with the package’s contents. Example:
<ItemGroup>
<PackageReference Include="MyTool" Version="1.2.3">
<PrivateAssets>all</PrivateAssets>
<ExcludeAssets>all</ExcludeAssets>
<GeneratePathProperty>true</GeneratePathProperty>
</PackageReference>
</ItemGroup>
<Target Name="RunMyTool">
<!-- PkgMyTool should be available here -->
<Exec Command="$(PkgMyTool)\tools\MyTool.exe" />
</Target>
This does restrict you to using one version of the package per project.PackageDownload
and address the tool relative to the NugetPackageRoot
:
<ItemGroup>
<PackageDownload Include="MyTool" Version="1.2.3" />
</ItemGroup>
<Target Name="RunMyTool">
<Exec Command="$(NugetPackageRoot)\mytool\1.2.3\tools\MyTool.exe" />
</Target>
($(NugetPackageRoot)
should resolve to C:\Users\me\.nuget\packages
on your machine - it should be defined in the generated nuget.g.props
file if you wanna confirm that.)
Off the top of my head I think there may be certain niche configurations in which PackageDownload
s get installed somewhere other than the NugetPackageRoot
location? Not sure. It’s a little tedious to mention the package version twice, of course.dotnet tool
, you can declare the dependency in a tool manifest. (Tool manifests are designed to be checked in to your repository.) Then it should get installed during restore, after which you can run it via dotnet
.
// dotnet-tools.json
{
"tools": {
"myTool": {
"version": "1.2.3",
"commands": ["myTool"]
}
}
}
<!-- MyProject.csproj -->
<Target Name="RunMyTool">
<Exec Command="dotnet tool run myTool" />
</Target>
This requires the package to have been authored as a tool package, of course. (Seems like in your case it was, so this is probably the best option for you.)All three of these have worked for me in the past.