好的做法:如何重用.csproj和.sln文件来为CI创建MSBuild脚本?

Gis*_*shu 7 .net msbuild continuous-integration

使用MSBuild作为构建运行器的无痛/可维护方式是什么?(原谅这篇文章的篇幅)

我只是在TeamCity尝试(我必须说这是非常棒的学习曲线和开箱即用的功能).我有一个SVN> MSBuild> NUnit> NCover组合工作.

我很好奇中等到大型项目是如何使用MSBuild的 - 我只是将MSBuild指向我的主sln文件.几年前我和NAnt一起度过了一段时间,我觉得MSBuild有点迟钝了.对于初学者来说,文档太密集/详细.

MSBuild似乎有一些特殊的魔法来处理.sln文件; 我尝试手工编写自定义构建脚本,按顺序链接/包括.csproj文件(这样我就可以进行自定义的事后构建任务).然而它呕吐(引用重复的目标导入).我假设大多数开发人员都不想搞乱使用msbuild proj文件 - 他们会对.csproj和.sln文件进行更改.是否有一些工具/ MSBuild任务可以从我不知道的现有.sln +其.csproj文件中反向设计一个新脚本?

如果我正在使用MSBuild来执行编译步骤,我不妨将Nant与exec任务一起使用到MSBuild来编译解决方案?我有这种唠叨的感觉,我错过了一些明显的东西.

我的最终目标是拥有一个MSBuild构建脚本

  • 它构建了解决方案
  • 它充当构建脚本而不是编译步骤.允许自定义的前/后任务.(例如,调用nunit来运行一个nunit项目(似乎尚未通过teamcity web UI支持))
  • 不要让开发人员改变解决方案.没有冗余; 不应该要求开发者在2个地方做同样的改变

Fil*_*urt 7

我没有尝试过TeamCity,但确实为我们的新BizTalk项目设置了一个Build环境.

开始之前,按照Sayed Ibrahim Hashimi我自己的问题的出色建议,我创建了一组MSBuild .proj和.targets脚本.

核心

您要执行的实际构建步骤的中心.targets脚本:

<Project DefaultTargets="Deploy" xmlns="...">
    <!-- omitted validation steps, see referenced post for details -->
    <PropertyGroup>
        <PullDependsOn>
            $(ValidateDependsOn);
            Validate;
        </PullDependsOn>
    </PropertyGroup>

    <PropertyGroup>
        <BuildDependsOn>
            $(PullDependsOn);
            PullFromVersionControl;
        </BuildDependsOn>
    </PropertyGroup>

    <PropertyGroup>
        <DeployDependsOn>
            $(BuildDependsOn);
            Build;
        </DeployDependsOn>
    </PropertyGroup>

    <Target Name="PullFromVersionControl" DependsOnTargets="$(PullDependsOn)">
        <Exec Command="..." />
    </Target>

    <Target Name="Build" DependsOnTargets="$(BuildDependsOn)">
        <MSBuild Projects="@(ProjectsToBuild)" />
    </Target>

    <Target Name="Deploy" DependsOnTargets="$(DeployDependsOn)">
        <Exec Command="..." />
    </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

第二个核心部分是您在.csproj文件中找到它们的配置目标

<Project xmlns="...">
    <PropertyGroup Condition=" '$(Environment)' == 'DEV' ">
        <SomeConfigKey Condition=" '$(SomeConfigKey)' == '' ">Foo</SomeConfigKey>
    </PropertyGroup>

    <PropertyGroup Condition=" '$(Environment)' == 'TEST' ">
        <SomeConfigKey Condition=" '$(SomeConfigKey)' == '' ">Bar</SomeConfigKey>
    </PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

项目

单个.csproj本身由a.targets文件表示,其中只包含构建所需的ItemGroup集合.

<Project xmlns="...">
    <ItemGroup>
        <!-- this group contains the list of items to pull from version control -->
        <Sources Include="@(Sources)" />
        <Sources Include="MyProjectRootDir" />
        <Sources Include="MyDependentProjectRootDir" />
    </ItemGroup>

    <ItemGroup>
        <ProjectsToBuild Include="@(ProjectsToBuild)" />
        <ProjectsToBuild Include="MyProject.csproj" />
    </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

把它放在一起

你实际上要用MSBuild执行的.proj将导入你的Configuration,你的Project(源代码文件)和Core(Pull,Build和Deployment命令)

<Project DefaultTargets="Deploy" xmlns="...">
    <Import Project="Config.targets"/>

    <Import Project="Project.targets"/>

    <Import Project="Core.targets"/>
</Project>
Run Code Online (Sandbox Code Playgroud)

使用这种方法,我能够重用包含源代码的.targets,以多种不同的组合构建我的大约50个项目,而不是创建VS解决方案来对它们进行分组.

我希望你会发现这很有用 - 如果你有兴趣,我可以添加更多细节.