如何在每次构建后自动将.targets文件添加到NuGet包中
你遇到的NU5019错误、targets文件不进包、原生DLL不复制三个问题,都是配置不符合NuGet约定+路径写错导致的,按下面步骤改即可:
1. 先修正.targets文件的基础配置
NuGet对build目录下自动导入的targets有硬性约定:文件名必须和你的NuGet包ID完全一致,不能多字符、少字符、加多余后缀。
- 把你放在csproj同级目录的targets文件重命名为
Com.CompanyName.Sdk.targets(如果你的包ID是其他值,严格和包ID对齐即可) - 右键该文件选择「属性」,将「生成操作」设置为
None,「复制到输出目录」设置为不复制,避免编译时把它拷到bin目录产生冗余文件。
2. 修正打包配置,解决NU5019找不到文件的错误
你之前报找不到文件,核心是两个配置写错:一是targets的打包路径多写了一层.targets后缀,二是路径匹配规则不对。以下两种配置方式二选一即可,不要同时使用避免冲突:
方式一:继续用手写nuspec配置(适配你当前的用法)
把nuspec里之前加的错误targets配置删掉,替换为下面这行:
<file src="Com.CompanyName.Sdk.targets" target="build\Com.CompanyName.Sdk.targets" />
注意:
src的路径是相对于nuspec文件所在目录的,如果你把targets、编译好的dll、nuspec都放在csproj同级目录,直接写文件名就不会报找不到文件的错误。如果执行打包命令时工作目录不对,补全相对路径即可。
方式二(推荐,SDK风格项目用这个容错率更高):删掉手写nuspec,直接在csproj里配置打包规则
你用的netcoreapp3.1属于SDK风格项目,完全不需要手动维护nuspec,直接在csproj里加如下配置即可:
<ItemGroup> <!-- 配置targets文件打包到build目录 --> <None Include="Com.CompanyName.Sdk.targets" Pack="true" PackagePath="build\" /> <!-- 配置原生DLL打包路径 --> <None Include="Com.CompanyName.Hashing.dll" Pack="true" PackagePath="lib\native\" /> </ItemGroup>
其他包元数据(版本、作者、描述)也可以直接在csproj的PropertyGroup节点里配置,执行dotnet pack时会自动生成标准nuspec,大幅降低路径写错的概率。
3. 补全.targets文件内容,实现原生DLL自动复制到输出目录
你之前把原生DLL放在lib\native路径下,这个路径的文件NuGet不会自动复制到消费项目的输出目录,需要在刚才的Com.CompanyName.Sdk.targets里加如下配置:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <!-- 读取包内lib/native目录下的所有原生DLL --> <NativeDlls Include="$(MSBuildThisFileDirectory)..\lib\native\*.dll" /> <!-- 将DLL标记为内容,编译/发布时自动复制到输出目录 --> <Content Include="@(NativeDlls)"> <Link>%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> </Content> </ItemGroup> </Project>
4. 验证配置是否正确
重新打包后,把生成的.nupkg文件当zip解压,检查包根目录下是否有build文件夹,且文件夹内存在和包ID同名的.targets文件。如果存在说明打包配置正确,安装到测试项目后编译,原生DLL就会自动复制到输出目录。
内容的提问来源于stack exchange,提问作者Ahmad

