【问题标题】:StyleCop integration with CI build process (Criuse Control, Nant, msbuild and StyleCop)StyleCop 与 CI 构建过程的集成(Criuse Control、Nant、msbuild 和 StyleCop)
【发布时间】:2010-11-20 16:23:08
【问题描述】:

我被要求将 StyleCop 集成到我们的 CI 构建过程中:

  • 我们的单个项目文件 (大)解决方案不受影响
  • 我不必使用任何第三方 工具

第一个要求(我还没有完全理解)是因为我们不想直接在整个解决方案上运行 StyleCop。显然,当 StyleCop 在 VS 中运行时,它会忽略某些指定要忽略的文件的属性。正因为如此,如果我们让它在开发机器上运行,我们将不断受到数千个我们尚未准备好处理的违规行为的打击。所以底线是我们希望能够只在构建服务器上运行它。

我们的构建环境目前包括:

巡航控制 > 执行 msbuild 的 nant 任务(通过 exec)

nant 任务如下:

<target name="buildSolution">       
    <echo message="Building solution..." />
    <exec program="C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe"                     
        commandline="${Project.SolutionFile} /t:Rebuild /p:Configuration=${Project.SolutionBuildConfiguration} /v:q" workingdir="." />      
</target>  

当我第一次看到这个时,我认为这将是一个以类似于执行 msbuild 的方式执行 StyleCop 的简单案例。

不过,StyleCop 是作为一组 dll 提供的......

所以这意味着我不能做我想做的事......我想......

我今天用谷歌搜索的所有文章都说“使用 StyleCopCmd”,由于 3rd 方工具限制,我也不能这样做。

我查看了该工具,它似乎实现了一个自定义的 nant 任务,该任务启动 StyleCopConsole、挂钩到几个事件并输出格式良好的报告。但是为了能够证明在内部创建任何工具的合理性,我需要能够充分解释为什么我不能在 nant 配置文件中实现我想要的。或以任何其他不涉及创建或使用工具的方式。理想情况下,如果我不必编写或使用任何工具,它会更快。

所以我的问题是,这可能吗?

【问题讨论】:

    标签: .net msbuild cruisecontrol.net nant stylecop


    【解决方案1】:

    我们已经做到了。只需按照以下步骤操作:

    • 在您的项目中创建一个目录并将所有 StyleCop 文件复制到那里(Microsoft.StyleCop.CSharp.dll、Microsoft.StyleCop.Targets 等)

    • 编辑 Microsoft.StyleCop.Targets 使其如下所示:

    --

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <UsingTask AssemblyFile="Microsoft.StyleCop.dll" TaskName="StyleCopTask" />
        <PropertyGroup>
            <BuildDependsOn>StyleCop</BuildDependsOn>
            <RebuildDependsOn>StyleCopForceFullAnalysis;StyleCop</RebuildDependsOn>
        </PropertyGroup>
        <PropertyGroup Condition="('$(SourceAnalysisForceFullAnalysis)' != '') and ('$(StyleCopForceFullAnalysis)' == '')">
            <StyleCopForceFullAnalysis>$(SourceAnalysisForceFullAnalysis)</StyleCopForceFullAnalysis>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopForceFullAnalysis)' == ''">
            <StyleCopForceFullAnalysis>false</StyleCopForceFullAnalysis>
        </PropertyGroup>
        <PropertyGroup Condition="('$(SourceAnalysisCacheResults)' != '') and ('$(StyleCopCacheResults)' == '')">
            <StyleCopCacheResults>$(SourceAnalysisCacheResults)</StyleCopCacheResults>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopCacheResults)' == ''">
            <StyleCopCacheResults>true</StyleCopCacheResults>
        </PropertyGroup>
    
        <!-- Define StyleCopTreatErrorsAsWarnings property. -->
        <PropertyGroup Condition="('$(SourceAnalysisTreatErrorsAsWarnings)' != '') and ('$(StyleCopTreatErrorsAsWarnings)' == '')">
            <StyleCopTreatErrorsAsWarnings>$(SourceAnalysisTreatErrorsAsWarnings)</StyleCopTreatErrorsAsWarnings>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopTreatErrorsAsWarnings)' == ''">
            <StyleCopTreatErrorsAsWarnings>true</StyleCopTreatErrorsAsWarnings>
        </PropertyGroup>
    
        <PropertyGroup Condition="('$(SourceAnalysisEnabled)' != '') and ('$(StyleCopEnabled)' == '')">
            <StyleCopEnabled>$(SourceAnalysisEnabled)</StyleCopEnabled>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopEnabled)' == ''">
            <StyleCopEnabled>true</StyleCopEnabled>
        </PropertyGroup>
    
        <!-- Define StyleCopOverrideSettingsFile property. -->
        <PropertyGroup Condition="('$(SourceAnalysisOverrideSettingsFile)' != '') and ('$(StyleCopOverrideSettingsFile)' == '')">
            <StyleCopOverrideSettingsFile>$(SourceAnalysisOverrideSettingsFile)</StyleCopOverrideSettingsFile>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopOverrideSettingsFile)' == ''">
            <StyleCopOverrideSettingsFile> </StyleCopOverrideSettingsFile>
        </PropertyGroup>
    
        <!-- Define StyleCopOutputFile property. -->
        <PropertyGroup Condition="('$(StyleCopOutputPath)' == '')">
            <StyleCopOutputPath>$(IntermediateOutputPath)</StyleCopOutputPath>
        </PropertyGroup>
        <PropertyGroup Condition="'$(StyleCopOutputFile)' == ''">
            <StyleCopOutputFile Condition="!HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)\$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
            <StyleCopOutputFile Condition="HasTrailingSlash('$(StyleCopOutputPath)')">$(StyleCopOutputPath)$(AssemblyName).StyleCopViolations.xml</StyleCopOutputFile>
        </PropertyGroup>
    
        <!-- Define all new properties which do not need to have both StyleCop and SourceAnalysis variations. -->
        <PropertyGroup>
            <!-- Specifying 0 will cause StyleCop to use the default violation count limit.
             Specifying any positive number will cause StyleCop to use that number as the violation count limit.
             Specifying any negative number will cause StyleCop to allow any number of violations without limit. -->
            <StyleCopMaxViolationCount Condition="'$(StyleCopMaxViolationCount)' == ''">100</StyleCopMaxViolationCount>
        </PropertyGroup>
    
        <!-- Define target: StyleCopForceFullAnalysis -->
        <Target Name="StyleCopForceFullAnalysis">
            <CreateProperty Value="true">
                <Output TaskParameter="Value" PropertyName="StyleCopForceFullAnalysis" />
            </CreateProperty>
        </Target>
    
        <!-- Define target: StyleCop -->
        <Target Name="StyleCop" Condition="'$(StyleCopEnabled)' != 'false'">
            <!-- Determine what files should be checked. Take all Compile items, but exclude those that have set ExcludeFromStyleCop=true or ExcludeFromSourceAnalysis=true. -->
            <CreateItem Include="@(Compile)" Condition="('%(Compile.ExcludeFromStyleCop)' != 'true') and ('%(Compile.ExcludeFromSourceAnalysis)' != 'true')">
                <Output TaskParameter="Include" ItemName="StyleCopFiles"/>
            </CreateItem>
    
            <Message Text="Forcing full StyleCop reanalysis." Condition="'$(StyleCopForceFullAnalysis)' == 'true'" Importance="Low" />
    
            <Message Text="Analyzing @(StyleCopFiles)" Importance="Low" />
    
            <!-- Run the StyleCop MSBuild task. -->
            <StyleCopTask
                ProjectFullPath="$(MSBuildProjectFile)"
                SourceFiles="@(StyleCopFiles)"
                AdditionalAddinPaths="@(StyleCopAdditionalAddinPaths)"
                ForceFullAnalysis="$(StyleCopForceFullAnalysis)"
                DefineConstants="$(DefineConstants)"
                TreatErrorsAsWarnings="$(StyleCopTreatErrorsAsWarnings)"
                CacheResults="$(StyleCopCacheResults)"
                OverrideSettingsFile="$(StyleCopOverrideSettingsFile)"
                OutputFile="$(StyleCopOutputFile)"
                MaxViolationCount="$(StyleCopMaxViolationCount)"
                />
    
            <!-- Make output files cleanable -->
            <CreateItem Include="$(StyleCopOutputFile)">
                <Output TaskParameter="Include" ItemName="FileWrites"/>
            </CreateItem>
    
            <!-- Add the StyleCop.cache file to the list of files we've written - so they can be cleaned up on a Build Clean. -->
            <CreateItem Include="StyleCop.Cache" Condition="'$(StyleCopCacheResults)' == 'true'">
                <Output TaskParameter="Include" ItemName="FileWrites"/>
            </CreateItem>
        </Target>
    </Project>
    
    • 将以下任务添加到要运行 StyleCop 的 NAnt 脚本中。只需将 NAnt 属性替换为对您的构建脚本有意义的属性或值。

          <msbuild project="${solutionfile}" target="ReBuild" verbosity="Quiet">
             <property name="CustomAfterMicrosoftCommonTargets" value="${path::combine(project:get-base-directory(), relative-path-to-Microsoft.StyleCop.Targets)}"/>
             <property name="Configuration" value="Release"/>
             <property name="StyleCopEnabled" value="true" />
             <property name="StyleCopOutputPath" value="${directory-to-dump-output-report-to}" />
             <arg value="/noconsolelogger" />
          </msbuild>
      

    【讨论】:

    • 嗨 Trumpi - 我现在正在尝试它 - 一个问题 - “target="ReBuild"” 是否保持不变或者现在指向我的原始构建目标(显示在我的发布)?
    • 还有,修改后的 Microsoft.StyleCop.Targets 文件的路径 - 这是构建文件还是解决方案文件的相对路径?
    • 嗯一直在谷歌搜索,并认为它需要进入我的原始任务,即复制 exec 调用 - 现在尝试......
    • 尝试但失败了,因为它试图执行 .net 2.0 msbuild 而不是 .net 3.5 msbuild - 谷歌搜索更多 - 我很接近,我能感觉到它哈哈 :)
    • 您可以尝试将 -t:net-3.5 作为参数传递给 NAnt 调用,但您需要使用 NAnt 0.86。该路径是相对于 NAnt 构建文件的,我认为您需要将其设为绝对路径。我会用正确的脚本修改答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 2014-07-25
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2012-08-10
    • 2012-07-12
    相关资源
    最近更新 更多