仅在重建时运行预构建事件

Posted

技术标签:

【中文标题】仅在重建时运行预构建事件【英文标题】:Run a Pre-Build Event only when Rebuilding 【发布时间】:2014-05-19 20:57:29 【问题描述】:

我正在编译一个项目,该项目依赖于其他几个开源项目(特别是 Zlib 和 LibTIFF),为此提供了 Windows makefile(旨在与 nmake 一起使用)。我想安排这样的事情,每当我对我的项目执行“重建”时,也会使用适当的配置(调试/发布、32/64 位等)重建开源项目。

我自己的项目相当简单,但并非微不足道。我浪费了最初的几天,试图弄清楚如何直接或使用 CMake 生成我自己的 nmake makefile。尽管有相当多的 GNU make 经验,但这让我失去了生存的意愿。康复后,我决定坚持使用 Visual Studio 项目文件来构建我自己的项目,并定义一个“预构建事件”以在供应商为我的开源库提供的 makefile 上执行 nmake。

例如,在我的 32 位发布版本的 Visual Studio 2010 项目页面中,使用英特尔 C++ 编译器,我将 Pre-Build Event 命令行编写为:

call "C:\Program Files (x86)\Intel\Composer XE 2013 SP1\bin\ipsxe-comp-vars.bat" ia32 vs2010
cd ..\..\..\zlib-1.2.8
nmake /f win32\Makefile.msc zlib.lib
cd ..\tiff-4.0.3
nmake /f Makefile.vc lib

(我意识到我也可以将上述内容放入一个批处理文件中,然后调用该批处理文件,但我不想给自己另一个文件来跟踪)。无论如何,这很好用,除了一件事:如果我决定更改我的配置,我想在两个库上执行“nmake clean”,以确保用我的新配置重建它们,类似于的:

call "C:\Program Files (x86)\Intel\Composer XE 2013 SP1\bin\ipsxe-comp-vars.bat" ia32 vs2010
cd ..\..\..\zlib-1.2.8
IF "%BUILDACTION%"=="REBUILD" nmake /f win32\Makefile.msc clean
nmake /f win32\Makefile.msc zlib.lib
cd ..\tiff-4.0.3
IF "%BUILDACTION%"=="REBUILD" nmake /f Makefile.vc clean
nmake /f Makefile.vc lib

不幸的是,我似乎无法确定任何满足 BUILDACTION 角色的环境变量,我也看不到定义一个直接的方法。那么,有什么方法可以做我想做的事情吗,还是我一无所有?

【问题讨论】:

【参考方案1】:

一旦您意识到Rebuild 目标只是一个存根,实际上由调用CleanBuild 组成(就像在典型的gnu makefile 中一样),解决方案就会出现:使用两个单独的目标,一个一个用于清洁,一个用于构建。您可以保留预构建事件,并为 Clean 添加一个。在文本编辑器中打开项目文件,并在末尾添加如下内容:

<Target Name="OnCleanOnly" AfterTargets="Clean">
  <Message Text="OnCleanOnly" Importance="High"/>
</Target>

Clean 目标被调用时,这个目标会被自动调用。当您在 VS 中执行 Clean 或 Rebuild 或在命令行上调用 msbuild myproject /t:Rebuild 时就是这种情况。

注意,你说 我意识到我也可以将上述内容放入一个批处理文件中,然后调用该批处理文件,但我不想给自己另一个文件来跟踪但我不会这么快就否定这个想法,因为它的主要优点是您可以通过运行批处理文件来测试构建事件本身是否正常。如果您想对嵌入在项目文件中的目标执行相同的操作,则必须启动命令行,确定要准确调用的目标并运行msbuild projectfile /t:target 来测试它。更多工作 :) 跟踪文件也是版本控制系统的工作,因此您不必担心。

【讨论】:

这看起来很有希望,但 GUI 似乎没有提供指定“清洁后事件”的机会,所以看起来我必须直接编辑 .vcxproj 文件。有一些文档(事实上,比我能找到的 nmake 文档多得多!)所以我会看一下。 是的,您确实必须手动编辑它。但不要害怕,它是非常可读的 xml :] 尤其是在使用识别它的文本编辑器时。最简单的实际上是使用 VS 本身来编辑项目文件,因为它具有用于项目文件的智能感知/自动完成/...。或者使用带有 msbuild 插件的 SublimeText。 我快走出困境了,但如果你能给我一些建议,我可以做。当我合并您建议的 XML 项目并添加(在 之后的行)“ (根据文档,执行命令中的回车很好),我收到错误消息“'nmake' 不是内部或外部命令,可运行程序或批处理文件”。它没有反对 'cd' 命令,但它似乎丢失了 'nmake' 的路径。有没有办法解决这个问题? 你打电话给ipsxe-comp-vars.bat了吗? nmake 通常不在您的 PATH 上,我猜 ipsxe-comp-vars.bat 设置了正确构建所需的所有环境变量。使用命令创建一个批处理文件,从“普通”命令行执行它(即不调用 ipsxe-comp-vars.bat 或任何 VS 的 xxvars.bat,运行批处理文件,检查它是否有效。仅当它有效时,您应该可以将其与 Exec 一起使用。 是的,就是这样!我假设已经设置了“本机 Microsoft”环境变量,并且所有 ipsxe-comp-vars.bat 所做的只是设置了额外的英特尔特定变量。显然情况并非如此,事实证明,调用 ipsxe-comp-vars.bat 或(Microsoft 等效项)vcvarsall.bat 也可以确保识别“nmake”。我还必须转义路径名中所需的引号。稍后我会单独发布一个答案来记录最终的解决方案。【参考方案2】:

Stijn 让我走上了正轨:最终的解决方案是手动在我的 .vcxproj 文件末尾添加以下部分(紧接在构成最后一行的 之前):

  <Target Name="OnCleanOnly" AfterTargets="Clean">
    <Exec Command="call &quot;C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat&quot; x86
                   cd ..\..\..\zlib-1.2.8
                   nmake /f win32\Makefile.msc clean
                   cd ..\tiff-4.0.3
                   nmake /f Makefile.vc clean" />
    <Message Text="Cleaning libraries" Importance="High" />
  </Target>

这可确保在每次从“构建”菜单中选择“清洁解决方案”或“重建解决方案”时运行“nmake clean”命令。这正是我希望达到的。

【讨论】:

【参考方案3】:

您可以按照以下流程进行操作:

    在您的项目中添加可执行文件 右键单击->可执行文件的属性。 将“项目类型”更改为“自定义构建工具” 申请 转到新创建的“自定义构建工具”选项卡。 在“命令行”部分添加您的命令。 指定命令行生成的输出文件的名称。 根据您的要求选择其他选项。 点击“确定” 对调试和发布配置都需要自定义构建的所有文件执行此操作

完成了!!!!

【讨论】:

【参考方案4】:

如果是重建,则可以使用参数 R 调用您的 bat,如果不是,则不使用。 IE。 Yourbat.bat R 然后只测试参数 (%1)。

call "C:\Program Files (x86)\Intel\Composer XE 2013 SP1\bin\ipsxe-comp-vars.bat" ia32 vs2010
cd ..\..\..\zlib-1.2.8
IF /i "%1"=="R" nmake /f win32\Makefile.msc clean
nmake /f win32\Makefile.msc zlib.lib
cd ..\tiff-4.0.3
IF /i "%1"=="R" nmake /f Makefile.vc clean
nmake /f Makefile.vc lib

我使用IF不区分大小写的/i参数(你可以使用rR

【讨论】:

谢谢,但我不太明白这有什么帮助,除非我可以在选择 Rebuild 而不是普通 Build 时自动添加“R”。如果每次我想进行重建时,我都必须打开项目页面并手动将“call YourBat.bat”更改为“call YourBat.bat R”,那么我的情况并没有比我好多少更改批处理文件本身的文本。如果我忘记这样做,我仍然会感到厌烦。关键要求是确定一些变量,文件可以通过该变量自动测试用户是否请求重新构建或普通构建。 用户在调用重建时与调用普通构建时有何不同? 在正常情况下,当用户想要从 Debug 切换到 Release,或从 32 位切换到 64 位时,会发生 Rebuild。例如,此时需要重新构建库以确保我们最终不会尝试将 32 位发布项目与 64 位调试库链接。

以上是关于仅在重建时运行预构建事件的主要内容,如果未能解决你的问题,请参考以下文章

在 ac-docker win10 中编译时出现构建错误,要求重建已编译的标头,因为自预编译标头以来文件已被修改

运行 yarn install 时如何避免 node-gyp 重建?

重建预编译头文件

每次我进行常规构建时,LPCXpresso都开始重建我的整个项目

Xcode 在没有任何更改时重建项目

如何停止 Maven 的验证阶段重建工件?