在每次构建之前运行自定义工具,即使它是最新的

Posted

技术标签:

【中文标题】在每次构建之前运行自定义工具,即使它是最新的【英文标题】:Run custom tool before each build even if it is up-to-date 【发布时间】:2019-12-27 12:57:59 【问题描述】:

我想将git describe --dirty --always --tags 的输出嵌入到我的程序中,以便轻松区分同一可执行文件的不同版本。为此,我生成了一个包含所述命令输出的源文件。

由于该命令生成一个以dirty 结尾的字符串,如果我的工作树中有任何尚未提交的修改文件,我无法真正定义何时重新生成我的源文件的触发器(例如@987654321 中所示@)。 为了解决这个问题,我编写了一个批处理脚本,它将现有源文件的内容与 git 命令的输出进行比较,并仅在必要时重新生成源文件。

我现在的问题是我需要在每次构建之前运行这个批处理脚本,即使 msbuild 认为项目是最新的。我尝试使用预构建事件,但如果项目是最新的,则不会触发它。我还尝试了自定义构建步骤并将一个不存在的文件配置为输出(这也是accepted answer 这里)。这会导致我的批处理脚本始终执行,但它也会导致为项目执行代码生成,即使我生成的源文件没有更改。

4>------ Build started: Project: TestProject, Configuration: Release Win32 ------
4>  Current git Version is 9.6-13-g2c753a1727-dirty
4>  Include with version number is up-to-date
4>  Generating code
4>  0 of 9106 functions ( 0.0%) were compiled, the rest were copied from previous compilation.
4>    0 functions were new in current compilation
4>    0 functions had inline decision re-evaluated but remain unchanged
4>  Finished generating code
4>  TestProject.vcxproj -> C:\bin\TestProject.exe
4>  TestProject.vcxproj -> C:\bin\TestProject.pdb (Full PDB)

我尝试将 Execute Before 设置为 ClCompile。这可能是原因吗?我也尝试了其他一些,但效果相同。

如果我生成的源文件已更新,我怎样才能始终运行我的批处理脚本但只让项目生成一个新的可执行文件?

【问题讨论】:

【参考方案1】:

我怎样才能始终运行我的批处理脚本但使项目只产生 如果我生成的源文件已更新,是否会生成新的可执行文件?

尝试将<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck> 添加到PropertyGroup

  <PropertyGroup Label="Globals">
     ...
    <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
  </PropertyGroup>

那么 VS 将始终运行该项目,并且如果输出 xx.exe 是最新的且未更改 xx.cpp 文件,则 ClCmpile 目标不会实际上创建新的xx.exe

更新:

我创建一个新的简单 C++ 项目,将其设置为 release 模式,并添加 DisableFastUpToDateCheck 属性。现在 vs 将始终构建项目。

我都使用pre-build eventcustom target which execute before ClCompile来执行命令git describe --dirty --always --tags

现在我的 msbuild 输出日志详细程度是 minimal

1.构建项目:

2.对源文件不做任何更改,重新构建项目:

3. 执行与 #2 相同的操作。同样的结果。

4.添加注释xx.cpp(不影响代码),构建项目:

5.Msbuild project build output verbosity 在您尝试获取有关构建过程中发生的详细信息时是一个很好的工具。对我来说,我总是将其设置为Detailed。对于这个问题,如果我们将其设置为Normal,我们可以找到:

在我看来:

    当我在代码中更改某些内容时,消息是1 of 10 functions (10.0%) were compiled, the rest were copied from previous compilation. 并且在比较#1和#4之后,我们可以得出结论,当它显示0 of xxx functions were compiled时,它实际上并没有花费时间生成代码,因此不会影响时间您的构建过程。

    关于它创建新可执行文件的原因,请参阅this document。在 vs 中,大多数目标都有其输入和输出。与 ClCompile 目标一样,xx.h 文件和 xx.cpp 文件是它的输入。此目标是否会执行不取决于输出文件是否早于输入。

    例如:当我在 xx.cpp 中添加注释时,代码实际上并没有改变。但是现在 xx.cpp 比早期版本的输出 xx.exe 更新。然后这一次构建引擎将执行 ClCompile 和 Link 目标以创建新的 xx.exe。并且代码生成是链接目标的一部分,由于代码本身没有变化,它会显示 0 of xxx functions were compiled 表示它不会真正生成,尽管这次将创建新的 xx.exe。

    所以在正常情况下,DisableFastUpToDateCheck 确实适用于这种情况,例如 #2 和 #3。根据你上面分享的图片,你必须做一些不改变源文件中的代码内容(编译了0个函数)但更新输入文件的修改日期的事情。

【讨论】:

没有效果。即使没有任何变化,它仍会执行代码生成步骤。 @sigy 嗨,朋友,请查看我的更新以进行一些故障排除以定位问题。(请参阅#2,#3,它应该可以工作)希望它有所帮助:)

以上是关于在每次构建之前运行自定义工具,即使它是最新的的主要内容,如果未能解决你的问题,请参考以下文章

Wix 自定义卸载操作 - 如何在 msi 删除文件之前运行

参数如何传递到 Visual Studio 的自定义构建工具中?

如何使用docker构建我自己的自定义Ubuntu ISO

使用 GRUB 的自定义代码?

在 Docker 中运行的自定义 Azure DevOps 构建代理上具有卷装载的测试容器

Codemagic 不适用于 iOS 中的自定义运行脚本?