zoukankan      html  css  js  c++  java
  • 在MSBuild中使用Task实现自动引用指定版本的NuGet包

    需求背景:

    桌面应用程序NeverForm依赖于MoreFramework。MoreFramework在维护过程中会经常性地升级版本号 e.g. 从1.00.001.01升级到1.01.022.02 最后两位是build计数。

    NeverForm使用CruiseControl.NET来实现持续集成。对MoreFramework的引用有一部分通过MSBuild脚本实现:

    -使用NuGet从 指定目录 获取 package.config中指定版本 的 MoreFramework的nuget包 e.g. MoreFramework.1.01.022.02.nupkg

    -NuGetInstall指令会把MoreFramework.1.01.022.nupkg编译成dll文件,并安装到packages目录 e.g. NeverFormSourcepackagesMoreFramework.1.01.022.02.nupkglib et40MoreFramework.dll

    -NeverForm对MoreFramework的引用添加是在工程文件里实现的 e.g.NeverForm.csproj。也就是在visual studio里添加引用。这里没有使用MSbuild脚本。

    当MoreFramework升级版本号时,目前的流程是:

    1)修改package.config文件,将版本号从1.00.001.01改为1.01.022.02 。

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
       <package id="MoreFramework" version="1.01.022.02" targetFramework="net471" />
    </packages>

    2)删除文件夹NeverFormSourcepackagesMoreFramework.1.00.001.01。

    3)新建文件夹NeverFormSourcepackagesMoreFramework.1.01.022.02lib et40(直接修改文件夹名字也可,但是大多数情况我们都要上传代码,删除+新建更方便trace。)

    4)将MoreFramework.dll拷贝到上述新建的文件夹中。

    5)在打开NeverForm工程,visualstudio里重新添加对MoreFramework的引用,因为路径变了,所以引用要重新添加。

    6)上传代码:package.config+新建的文件夹+修改引用后的工程文件。

    7)在CruiseControl.NET中build。

    上述流程中2,3,4步骤,完全是为了让重新指定MoreFramework的引用路径。packages文件夹的内容正常都是NuGet生成的。很明显这是一个笨拙的操作。

    既然使用了CruiseControl.NET,那么像引用这种操作当然应该在MSBuild里添加,尽可能少的依赖csproj文件,甚至完全脱离它。

    可是MoreFramework的路径是随着版本升级而变化的。不可能每次升级都去修改ReferencePath。

    有一种解决办法是:

    不使用NuGet,而是指定一个固定目录作为ReferencePath。将所有引用的dll都放到这个目录,然后在MSBuild中添加引用。每次升级直接用新的dll覆盖掉旧的就可以了。

    这是一个比较常规的做法,很多引用的第三方API都可以这样处理。

    但是对于有版本号管理的,公司内部开发的framework,这样简单的做法就会丢失版本号信息。开发者无法从代码层面trace framework的升级轨迹。

    换句话说,如果能减少繁琐多余的操作,当然是使用NuGet来管理framework更好。

    解决方案:

    在NuGetInstall完成后,我们需要msbuild去读取package.config文件,根据读取到的版本号,返回引用路径,然后将该路径下的MoreFramework添加到引用中。

    下面是NuGetInstall的MSBuild脚本:

    <Target Name="NuGetPackages">
            <CreateItem
                  Include="$(SourcePath)packages.config">
            <Output
                TaskParameter="Include"
                ItemName="PackageConfigs"/>
            </CreateItem> 
            
            <NuGetInstall Package="%(PackageConfigs.FullPath)" OutputDirectory="$(SourcePath)Packages" ToolPath="D:BuildTools" Source="D:BinariesNuGet"/>
    </Target> 

     使用Task:

    <Import Project="$(BuildTools)Build.Tasks.Never.targets" />
    
    <Target Name="BuildVersion">
         <GetPackageVersionTask PackageConfigFileName="$(SourcePath)packages.config" PackageID="MoreFramework">
              <Output TaskParameter="Version" PropertyName="MoreFrameworkVersion"/>
         </GetPackageVersionTask>
         <PropertyGroup>
              <MoreFrameworkReferencePath>$(SourcePath)packagesCosmos.CoreUI.$(CoreUIVersion)lib
    et40</MoreFrameworkReferencePath> 
    </
    PropertyGroup>
    </Target>

    Task代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using NuGet;
    
    namespace Build.Tasks.Never
    {
        public class GetPackageVersionTask : Task
        {
            [Required]
            public string PackageConfigFileName { get; set; }
    
            [Required]
            public string PackageID { get; set; }
    
            [Output]
            public string Version { get; private set; }
    
            public override bool Execute()
            {
                PackageReferenceFile packageFile = new PackageReferenceFile(PackageConfigFileName);
                foreach (PackageReference packageReference in packageFile.GetPackageReferences())
                {
                    if (packageReference.Id.Equals(PackageID))
                    {
                        Version = packageReference.Version.ToString();
                        this.Log.LogMessage("Package ID = {0},version = {1}", new object[] { PackageID, Version });
                        return true;
                    }
                }
                return false;
            }
        }
    }

    targets文件:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <UsingTask AssemblyFile="Build.Tasks.Never.dll" TaskName="Build.Tasks.Never.GetPackageVersionTask"/>
    </Project>

     *.targets文件并不是build出来的,而是manual wirte的。

    * GetPackageVersionTask生成的dll必须和.targets在同一个文件夹

  • 相关阅读:
    谷歌大规模机器学习:模型训练、特征工程和算法选择 (32PPT下载)
    (转) 深度强化学习综述:从AlphaGo背后的力量到学习资源分享(附论文)
    (转) Supercharging Style Transfer
    Summary on deep learning framework --- TensorFlow
    (转) How a Kalman filter works, in pictures
    Torch 两个矩形框重叠面积的计算 (IoU between tow bounding box)
    C、C++基础和编程风格 (转)
    Linux && shell
    求最短路径的条数
    一个链表中包含环,请找出该链表的环的入口结点。
  • 原文地址:https://www.cnblogs.com/nevermore-wd/p/12876244.html
Copyright © 2011-2022 走看看