Visual Studio NuGet将文件复制到项目目录中

qpgpyjmq  于 2023-10-23  发布在  其他
关注(0)|答案(2)|浏览(344)

我已经创建了一个.nuspec文件,它打包了一堆.proto文件,以便在项目之间共享。这太棒了不幸的是,对于要构建的.proto文件,它们需要实际复制到项目目录中,而不仅仅是引用。请注意,这是一个.NET Core项目。
现在,我的定义创建了一个包,当使用它时,它引用项目中的文件,但这些文件仍然驻留在原始的.Nuget文件夹中,这不是我真正需要的。
下面是我现在得到的.nuspec定义:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>GRPCProtoFiles</id>
        <version>1.0.0</version>
        <authors>Author</authors>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>.proto files NuGet package.</description>
        <dependencies>
          <dependency id="Google.Protobuf" version="3.14.0"/>
          <dependency id="Grpc" version="2.35.0"/>
        </dependencies>
        <contentFiles>
          <files include="any/any/Protos/**/*.proto" buildAction="None" copyToOutput="false" />
        </contentFiles>
    </metadata>
    <files>
        <file src="**\*.proto" target="contentFiles\any\any\Protos" exclude="google\**" />
    </files>
</package>

我知道“构建操作”当前设置为“无”,但我可以在安装软件包时将文件放置在正确的文件夹中后将其修复。实际上,如果我试图将proto文件的构建操作设置为正确的(即Protobuf编译器),那么我会得到一个错误,因为文件不在它们应该在的地方。
我做错了什么?
编辑:
好吧,我已经读了一些关于可能发生的事情和原因。具体this的回答给了我很多见解。然而,我想知道我如何才能真正做我需要做的事情。现在看来,我想做的是不可能与NuGet和我使用错误的工具的工作。但是除了这个限制之外,NuGet似乎是理想的-它能够从源项目中选择.proto文件并发布它,而不是为各种目标系统预先构建的库。
我可能会添加一个预构建操作来将文件复制到项目目录中,但我不知道如何引用源NuGet包文件夹(特别是如果版本更改)。你知道这个问题是否有解决方案吗?

uqzxnwby

uqzxnwby1#

我知道你的想法。首先,使用Build Action None将这些proto文件打包到nupkg中。然后使用主项目下的pre-build事件来处理nupkg中的文件。问题是如何使用msbuild属性从nupkg获取文件,因为Net Core项目使用Link properties来引用主项目下的文件,而不是将真实的nuget文件复制到主项目文件夹中。
在Link属性下,您无法更改该文件的Build Action,因为它实际上不存在于主项目文件夹下,并且主项目没有责任处理该文件。
有两个函数可以解决它:

功能一

您可以直接在nupkg本身下执行此操作,之后,proto文件将在构建过程中使用nuget包自动复制。尝试以下步骤,您不应该从安装nuget包的其他主项目添加任何复制任务。
你必须使用<packages_id>.props/targets文件到nupkg中才能得到你想要的。请参阅此官方文件。

**1)**创建一个名为<packages_id>.props的文件。在你的身边,它应该被命名为GRPCProtoFiles.props,这样它就可以工作了。

**2)**在GRPCProtoFiles.props文件中添加以下内容:

<Project>

    <Target Name="CopyFiles" BeforeTargets="Build">
        <ItemGroup>
            <File Include="$(MSBuildThisFileDirectory)..\contentFiles\**\*.*"></File>
        </ItemGroup>
        <Copy SourceFiles="@(File)" DestinationFolder="$(ProjectDir)\Protos"></Copy>
    </Target> 

</Project>

**3)**在GRPCProtoFiles.nuspec文件中添加这些,以将props文件包含到nupkg中:

<file src="build\*.props" target="build" />

整个GRPCProtoFiles.nuspec文件应该是这样的:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>GRPCProtoFiles</id>
        <version>1.0.0</version>
        <authors>Author</authors>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>.proto files NuGet package.</description>
        <dependencies>
          <dependency id="Google.Protobuf" version="3.14.0"/>
          <dependency id="Grpc" version="2.35.0"/>
        </dependencies>
        <contentFiles>
          <files include="any/any/Protos/**/*.proto" buildAction="None" copyToOutput="false" />
        </contentFiles>
    </metadata>
    <files>
        <file src="xxx.proto" target="contentFiles\any\any\Protos" exclude="google\**" />
        <file src="build\*.props" target="build" />
    </files>
</package>

**4)**然后重新打包新版本的nuget项目。在安装新版本之前,请先清理nuget缓存或删除C:\Users\xxx\.nuget\packages下的所有文件
**安装nuget包后,**请点击Build按钮执行目标。

更类似于这个问题。

功能二

您无法对nupkg本身执行任何内部步骤。您可以直接从外部主项目复制文件。

1)不要为您的nuget包执行Function One下的任何步骤。用你的旧金块包。

修改Project A的csproj文件,该文件安装了GRPCProtoFiles nuget包。
PackageReference GRPCProtoFiles添加<GeneratePathProperty>true</GeneratePathProperty>,生成独占属性为$(PkgGRPCProtoFiles),获取nupkg内容的路径。
整体是这样的:

<ItemGroup>
    <PackageReference Include="GRPCProtoFiles" Version="1.0.0">
      <GeneratePathProperty>true</GeneratePathProperty>
    </PackageReference>
 </ItemGroup>

然后,右键单击项目A->属性->构建事件->在预构建事件命令行下添加这些:

xcopy  /s /e /y /i  $(PkgGRPCProtoFiles)\contentFiles\any\any\Protos  $(ProjectDir)\Protos

或者,将此目标添加到ProjectA.csproj文件中:

<Target Name="CopyFiles" BeforeTargets="PrepareForBuild">
        <ItemGroup>
            <File Include="$(PkgGRPCProtoFiles)\contentFiles\**\*.*"></File>
        </ItemGroup>
        <Copy SourceFiles="@(File)" DestinationFolder="$(ProjectDir)\Protos"></Copy>
</Target>

pkwftd7m

pkwftd7m2#

我知道这是几年前的事情了,但我在做同样的工作时遇到了这个,我能够使用与上面第一个函数类似的语法添加我的proto文件。
我实际上是创建了3个不同的.nuspec文件和3个.props文件,一个用于客户端,一个用于服务器,一个用于两者。因此,根据使用情况,您可以使用PackageBlah-(client|server|both).X.X.X并获得正确的proto文件 * 和 *,生成的代码将是您所期望的。
首先,我的nuget包 only 由proto文件组成,因此您的目录结构可能会略有不同。
我从一个nuspec文件开始,它有一个用于<files>的文件,将我的proto文件放在包中一个名为protos的目录中,并将props文件放在build文件夹中。

<files>
        <file src="*.proto" target="\protos" />
        <!-- This line below will change if you're in the nuspec for client|server|both -->
        <file src="build-props\*-server.props" target="build" />
    </files>

.props文件看起来像这样(这是整个文件):

<Project>    
    <ItemGroup>
        <Protobuf Include="$(MSBuildThisFileDirectory)..\protos\*.proto" GrpcServices="Both" ProtoRoot="$(MSBuildThisFileDirectory)..\protos">
            <Link>protos\%(Filename)%(Extension)</Link>
        </Protobuf>
    </ItemGroup>        
</Project>

请记住,GrpcServices属性将根据您正在构建的包而有所不同。
对我来说,最终的结果是我的项目包含了正确的protobuf引用,并且在build时运行的protoc进程知道在哪里可以找到proto文件。

相关问题