Can I specify the output path for the MSBuild tag?

后端 未结 4 2018
猫巷女王i
猫巷女王i 2021-02-07 08:29

Is it possible to specify a different folder for the output of the following file?


  PreserveNe         


        
相关标签:
4条回答
  • 2021-02-07 08:52

    There is no way to specify an output folder additionally AFAIK, but you can copy the file before or after the build.

    0 讨论(0)
  • 2021-02-07 09:05

    You can, but not with 'Content'. It depends on the item task, but most of the built-in ones you could hack in, arnt worth the trouble or side-effects.

    There is a basic well worn path for dealing with this :) This also avoids the nasty PostBuild cmd shell way if you are doing .Net, and uses the actuall build process.

    I didnt see any other answers like this, using strieght up MSBuild, where I think the heart of the OPs question is. This is the core concept, and the shortest path, baring finding an item type that has a 'relative to outputpath' path parameter with no side effects.

    1) Post Process Style:

    <ItemGroup>
      ...
      <MyTargets Include="test.stl"/>
      ...
    </ItemGroup>
    

    Then at the bottom (using whatever paths you are after):

    <PropertyGroup>
      <MyDeployDir>$(SolutionDir)$(Configuration)</MyDeployDir>
      <MyOtherDeployDir>$(SolutionDir)$(Configuration)\Templates</MyDeployDir>
    </PropertGroup>
    

    Then your existing MS build includes (dont add this, is here as a marker):

    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    

    Then the 'after build':

    <Target Name="AfterBuild">
      <Copy SourceFiles="@(MyTargets)" DestinationFolder="$(MyDeployDir)" SkipUnchangedFiles="true" />
      <Copy SourceFiles="@(MyOtherTargets)" DestinationFolder="$(MyOtherDeployDir)" SkipUnchangedFiles="true" />
      <Copy SourceFiles="@(MyTargets2)" DestinationFolder="$(MyDeployDir)\IHeardYourMomLikesGrapeNuts" SkipUnchangedFiles="true" />
    </Target>
    

    The fundemental issue is that project items dont do anything by default, they have a type like 'Content' or 'MyTarget'. Its those types that say what will happen. You might be able to find a task, or type, or build script include that has what you want, but there is nothing intrinsic about a item in an itemgroup as far as what will happen with that file during build. The above is a balance between power of a specially built 'task' but with out all trouble.

    Once you add

     <ItemGroup>
        <MyOutFiles Include="xxx.xxx" />
    

    one time to the project file, it will then appear in the BuildAction list for any file, where you can set on any file without having to edit the proj file manually.


    2) In one step

    In later versions of MSBuild you can embed an 'ItemGroup' inside the 'AfterBuild' target and do the above or do other fancy things without touching the rest of the file. This allows for instance grabbing the resultof the build using a simple Include and displacing it somewhere else. This is all without doing RoboCopy anything or resorting to the more complicated build target function processing.

    <Target Name="AfterBuild">
      <ItemGroup>
        <MyOutFiles Include="$(OutDir)*.*" />
      </ItemGroup>
      <Copy SourceFiles="@(MyOutFiles)" DestinationFolder="$(SolutionDir)\Application" SkipUnchangedFiles="true" />
    

    Edit (due to down vote?, posters comment since removed):

    To disambiguate the possible methods and to reiterate, this method does not use MSBuild 'functions' or alternate tasks like 'RoboCopy' but was meant to show a more pure MSBuild style using core functionality like one would use in making item tasks like 'Content' itself.

    The question was can I specify a 'differnt folder for the following file' and can I do this for the content tag. You can reroute all of a BuildAction using MSBuild functions, however I dont beleive that was the question.

    You can do this is one step as shown above, so I dont think this is any more complicated and belive it easier to read. Below is the short form, and lets him create his own BuildAction that can be handled anyway he wants. So no, you cant tell 'Content' to pick another folder for a particular file marked as 'Content', but you can make another build action that does fairly easily. You could also inject meta info into the StlFiles tag that directs the action sothat you could set it on the tag itself or have the StlFiles hook earlier in the process like content would, but thats more complicated.

    <StlFiles Include="test.stl" />         
    ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="@(StlFiles)" DestinationFolder="$(SolutionDir)\Release\MyTypes" SkipUnchangedFiles="true" />
    
    0 讨论(0)
  • 2021-02-07 09:07

    A different output folder can be specified by using the Link metadata on None/Content items:

    <Content Include="test.stl">
      <Link>some\folder\%(Filename)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    

    When using wildcards in an include statement, this is also the way to preserve the directory hierarchy, even for files coming from outside the project directory:

    <Content Include="..\shared\**\*">
      <Link>some\folder\%(RecursiveDir)%(Filename)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    

    In SDK-based projects (default for ASP.NET Core / .NET Core / .NET Standard projects) using a 2.0.0+ SDK, the same can be achieved using the LinkBase metadata:

    <Content Include="..\shared\**\*" LinkBase="some\folder" CopyToOutputDirectory="PreserveNewest" />
    
    0 讨论(0)
  • 2021-02-07 09:07

    This functionality isn't built into the Content item. But you can tack it on by adding a target to your project file.

    In your project you currently have this:

    <ItemGroup>
      <Content Include="test.stl">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
    

    Assuming you want that one specific file copied to a different location, add this to the end (before the closing "Project" tag):

    <Target Name="CopyStl" AfterTargets="AfterBuild">
      <!-- One or the other of these Copy tasks should do what you want --> 
      <Copy Condition="'%(Identity)' == 'test.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(OutputPath)\path\under\outputpath" />
      <Copy Condition="'%(Identity)' == 'test.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(MSBuildProjectDirectory)\..\path\outside\project" />
    </Target>
    

    If you want to add a few more files to copy to the same folder, try this instead:

    <Target Name="CopySomeFiles" AfterTargets="AfterBuild">
      <!-- One or the other of these Copy tasks should do what you want --> 
      <Copy Condition="'%(Identity)' == 'test.stl' AND '%(Identity)' == 'test2.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(OutputPath)\path\under\outputpath" />
      <Copy Condition="'%(Identity)' == 'test.stl' AND '%(Identity)' == 'test2.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(MSBuildProjectDirectory)\..\path\outside\project" />
    </Target
    
    0 讨论(0)
提交回复
热议问题