As part of my build process I want to run a dotnet tool before the compile.
作为构建过程的一部分,我想在编译之前运行一个dotnet工具。
I can add this section to my sdk project file:
我可以将此部分添加到我的SDK项目文件中:
<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?
有没有办法用环境变量替换PATH?
I have tried adding GeneratePathProperty="true"
to the PackageDownload but $(PkgMyTool) is undefined.
我尝试将GeneratePathProperty=“true”添加到PackageDownload中,但$(PkgMyTool)未定义。
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.
我还尝试使用
引用该工具,但由于SDK不兼容而失败。我的工具是netcore3.1,这个项目是netStandard2.0。
更多回答
优秀答案推荐
As you learned, PackageDownload
doesn’t yet support GeneratePathProperty
. Here are a couple of workarounds you could try, though:
正如您所了解到的,PackageDownload还不支持GeneratePathProperty。不过,以下是几个您可以尝试的解决方法:
- Declare your build-time dependency using
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.
- Use
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.
- If your tool was packaged as a
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.
这三点在过去都对我很管用。
The best solution I had success with thus far is this:
到目前为止,我用过的最好的解决方案是:
<Target Name="PreBuild" BeforeTargets="CoreCompile">
<Exec Command="dotnet tool update MyTool --tool-path=$(TargetDir)\tools --version=1.0.1" />
<Exec Command="$(TargetDir)\tools\MyTool <MyOptions> />
</Target>
And it DOES save me from the nitty gritty details like \netcoreapp3.1\any
but it does not reuse the tool from NuGet cache, meaning it has to be downloaded on every build.
而且它确实省去了像\netcoreapp3.1\any这样的细节,但它不会重用NuGet缓存中的工具,这意味着每次构建时都必须下载该工具。
I still hope someone will provide a better answer.
我仍然希望有人能提供一个更好的答案。
You can use only the macros provided by the framework. You can find them here. Almost all of them are referring to the relative path of your project. I suggest you to copy your tool inside a project folder and you can make use of these macros.
您只能使用框架提供的宏。你可以在这里找到他们。几乎所有这些都是指你的项目的相对路径。我建议你把你的工具复制到一个项目文件夹里,这样你就可以使用这些宏了。
更多回答
As you guessed, my package was already a tool package, so the third of your suggestions was my go-to solution and it worked right off the bat, thanks a lot.
正如你所猜到的,我的包已经是一个工具包,所以你的第三个建议是我的首选解决方案,它立刻奏效了,非常感谢。
'Copy your tool' sounds easier than it is, dotnet tools are multiple (sub)directories with different frameworks in separate directories.
“复制你的工具”听起来比实际上容易,DotNet工具是多个(子)目录,不同的框架在不同的目录中。
我是一名优秀的程序员,十分优秀!