使用 vc2010 和 msbuild 的多个构建规则

Posted

技术标签:

【中文标题】使用 vc2010 和 msbuild 的多个构建规则【英文标题】:multiple build rules using vc2010 and msbuild 【发布时间】:2010-12-03 02:05:29 【问题描述】:

我在 VS2010 中管理一个 C++ 项目,并希望在使用 C++ 编译器之前让所有 .cpp 文件通过外部工具运行。所有迹象似乎都表明这是可能的。例如,请参阅here。

由于这将发生在多个项目中,因此将这个功能放在一个属性表中,然后在任何地方都导入这个属性表是有意义的。在我接触属性表之前,它的整体看起来是这样的:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
    <ExtensionsToDeleteOnClean>...</ExtensionsToDeleteOnClean>
    <CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>...</AdditionalIncludeDirectories>
      <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
    </ClCompile>
    <Link>
      <AdditionalDependencies>...</AdditionalDependencies>
    </Link>
      <Outputs>...</Outputs>
    </CustomBuildStep>
  </ItemDefinitionGroup>
</Project>

根据上面的链接文档,我添加了以下几行:

<Project>
  <PropertyGroup>
    ...
    <CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
  </PropertyGroup>
  ...
  <ItemGroup>
    <CustomBuild Include="*.cpp">
      <Message>Running Custom Build Step</Message>
      <Command>dummy</Command>
      <Outputs>dummy</Outputs>
    </CustomBuild>
  </ItemGroup>
</Project>

这似乎没有任何效果,而且我的自定义构建工具从未在 ClCompile 之前运行。我尝试了各种移动和重命名标签的方法(例如,Xml 编辑器抱怨 CustomBuild 根据架构甚至无效),但没有任何效果。

我做错了什么?

【问题讨论】:

【参考方案1】:

虽然这是一个非常古老的问题,但我会尝试回答。

Include 属性期望在项目目录中找到 *.cpp 文件。如果 Project 目录中没有 .cpp 文件,则此 CustomBuild“任务”将永远不会启动。

OP 本可以做的是

<CustomBuild Include="**\*.cpp">
    <Message>Custombuild kicking in</Message>
    <Command>echo %(Identity)</Command>
    <Outputs>dummy</Outputs>
</CustomBuild>

而不是

<CustomBuild Include="*.cpp">
...

他会对项目目录的所有子目录中的所有 .cpp 文件执行 CustomBuild 操作,而不仅仅是等待编译的 .cpp 文件。

如果项目目录下的 .cpp 文件不可用(使用此类项目目录结构时可能发生),则 OP 必须明确指向正确的“根”目录。

【讨论】:

【参考方案2】:

或者,您可以通过在每个包含的 ClCompile 上运行 Exec 任务来节省通配符的使用。

<Target Name="ProcessClCompileFiles" BeforeTargets="ClCompile" Condition="'@(ClCompile)'!=''">
  <Message Text="== Starting processing cpp files ==" Importance="High"/>
  <Exec Command="echo processing %(ClCompile.filename)%(ClCompile.extension) &amp; ////YOUR COMMAND HERE////" />
</Target>

作为注释。这需要在此目标之前初始化 ClCompile 项目组。如果您要创建一个动态添加 ClCompile 的目标,则必须确保这发生在此 Target 被调用之前。

另一个注意事项是,如果 ClCompile 项目组中有任何项目,这些 Exec 任务将始终运行。如果您有应该跳过它们的条件(例如,已处理),请使用 Condition="A=B"

为了方便参考,下面是如何验证它是否没有创建文件以及是否创建了文件;如果文件过期:

Condition="!Exists('$(OutDir)%(Filename)%(Extension)') OR ($([System.DateTime]::Parse('%(ClCompile.ModifiedTime)').Ticks) > $([System.IO.File]::GetLastWriteTime('$(OutDir)%(Filename)%(Extension)').Ticks))"

【讨论】:

以上是关于使用 vc2010 和 msbuild 的多个构建规则的主要内容,如果未能解决你的问题,请参考以下文章

msbuild 不尊重 .sln 文件设置

VS2010:如何运行 devenv 以不并行化构建

如何使用 MSBuild 构建具有 VS2010 配置的 VS2015 解决方案?

让 MSBuild 和 CruiseControl .NET 构建和部署 VS2010 数据库项目

Visual Studio 2XXX、MSbuild、VC++2XXX、平台工具集和 Windows SDK 兼容性

Jenkins 和 MSBuild 不会构建包含相同 dll 的多个版本的 WiX .msi