3

如何.cmd在 Visual Studio(分别为 2005、2008、2010、2012 和 2013)项目的预链接阶段中运行脚本来确定这是完全重建(Build.RebuildSolution/ Build.RebuildOnlyProject)还是“普通”构建(Build.BuildSolution/ Build.BuildOnlyProject)?

这是一个外部脚本(LuaJIT,如果你必须知道的话),我不想在项目的每个构建中都重新构建库。相反,我想将完全重建限制在我完全选择该选项的情况下。

4

4 回答 4

2

.cmd在 Visual Studio(分别为 2005、2008、2010、2012 和 2013)项目的预链接阶段中运行的脚本如何确定这是完全重建......还是“普通”构建......?

我不知道您所要求的确切事情是否可以完成 - 也许其他人知道该怎么做。但是,我会建议另一种方法。

我的方法是将 Lua 库的构建从预链接步骤中删除到单独的 Visual Studio NMake 项目。如果您创建一个 NMake 项目,您将能够知道正在发生哪种类型的构建(构建重建)。

请注意,更高版本的 Visual Studio 仅将项目类型称为“Make”。出于讨论的目的,我将项目类型称为“NMake”。我相信这只是命名上的差异,两个版本之间的底层构建项目保持不变。

作为一个简单的测试,我创建了两个 Visual Studio 应用程序:1) 一个调用批处理文件以创建静态库的 NMake 项目,以及 2) 一个使用步骤 1 中的库的控制台应用程序。

NMake 项目

在 Visual Studio 中,如果您创建一个新的 NMake 项目,您将看到一个对话框,允许您提供 MS-DOS 命令:

新建项目的对话框

如您所见,有以下命令:Build、Clean、Rebuild 等。我没有带有我的命令的上述对话框的屏幕截图,但这是我的 NMake 项目的属性:

NMake lib 项目属性

我的构建命令只是检查输出文件(lua.lib)是否存在。如果它不存在,则调用rebuild.bat批处理文件。我的重建命令总是调用批处理文件。我的 Clean 命令只是删除输出。我不太确定输出命令的用途,但我只是填写了构建输出(lua.lib)的路径。

现在,如果您进行构建,则仅当 lua.lib 文件不存在时才会创建它。如果它已经存在,则什么也不做。如果您进行重建,则会创建一个新的 lua.lib 文件。

控制台应用程序

在我的控制台应用程序中,我添加了对 NMake 项目的引用 - 这样 NMake 项目就在控制台应用程序之前构建。这是控制台应用程序的参考页面:

应用程序参考

我还在应用程序的链接阶段添加了 lua.lib 文件作为输入:

应用程序的链接属性

构建控制台应用程序时(在构建期间),如果需要,它将构建 NMake 项目,并在链接器阶段使用输出(lua.lib)。重新构建控制台应用程序时(在重新构建期间),它还将重新构建 NMake 项目。

其他想法

我上面的屏幕截图只显示了属性的调试版本。您的项目必须考虑发布版本。可能有一个 VS 宏来处理这个问题,但我不确定,因为自从我用 C/C++ 做任何事情以来已经很久了。

在上面的测试中,我使用单个构建批处理文件进行构建和重建。显然,您可以这样做,也可以使用不同的批处理文件。

于 2013-12-05T02:05:51.107 回答
0

好的,这将是一个漫长的过程。

首先 - 不要按原样使用我的代码 - 这是一个有很多黑客攻击的可怕代码,我不知道 msbuild 默认情况下如此糟糕(似乎在工作中我可以访问更多让生活更轻松的命令) . 还有一件事 - 似乎 vcxproj 在某些时候坏了 - 我无法将我想要的方式BeforeRebuildAfterRebuild目标集成 - 我不得不重新定义孔Rebuild目标(它位于 C:\Windows\Microsoft.NET\Framework\ v4.0.30319\Microsoft.Common.targets)

所以,想法如下:当重建发生时,我们创建一个锚。然后,在 PreLink 阶段,我们执行能够使用创建锚点的 cmd。如果锚点到位——我们处理重建,如果没有锚点——这是一个简单的构建。重建完成后 - 我们删除锚点。

vcxproj 文件中的修改:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ....
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    ....
    <PreLinkEventUseInBuild>true</PreLinkEventUseInBuild>
    ....
  </PropertyGroup>
  ....
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    .....
    <PreLinkEvent>
      <Command>D:\PreLink\b.cmd</Command>
    </PreLinkEvent>
    .....
  </ItemDefinitionGroup>
  .....
  <Target Name="BeforeRebuild">
    <Exec Command="echo 2 &gt; D:\PreLink\2.txt" />
  </Target>
  <Target Name="AfterRebuild">
    <Exec Command="del D:\PreLink\2.txt" />
  </Target>
  <!-- This was copied from MS file -->
  <PropertyGroup>

    <_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' != ''">$(MSBuildProjectDefaultTargets)</_ProjectDefaultTargets>
    <_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' == ''">Build</_ProjectDefaultTargets>

    <RebuildDependsOn>
      BeforeRebuild;
      Clean;
      $(_ProjectDefaultTargets);
      AfterRebuild;
    </RebuildDependsOn>

    <RebuildDependsOn Condition=" '$(MSBuildProjectDefaultTargets)' == 'Rebuild' " >
      BeforeRebuild;
      Clean;
      Build;
      AfterRebuild;
    </RebuildDependsOn>
  </PropertyGroup>


  <Target
      Name="Rebuild"
      Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
      DependsOnTargets="$(RebuildDependsOn)"
      Returns="$(TargetPath)"/>
  <!-- End of copy -->
</Project>

cmd看起来像这样:

if exist 2.txt (
    echo Rebuild818181
) else (
    echo Build12312312 
)

Output窗口的输出:

1>Task "Exec" (TaskId:41)
1>  Task Parameter:Command=D:\PreLink\b.cmd
1>  :VCEnd (TaskId:41)
1>  Build12312312 (TaskId:41)

需要改进的地方:

  1. 使用普通变量而不是外部文件(似乎MsBuild 扩展包应该这样做)

  2. 可能会找到一种仅覆盖BeforeRebuildAfterRebuild不是覆盖孔Rebuild部分的方法

于 2013-12-01T19:26:11.967 回答
0

这可能有点骇人听闻,但在.csproj文件中有部分

<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>

您可以从 BeforeBuild设置一个变量并从 cmd 脚本中检索它。稍后在 AfterBuild 中重置此变量,您应该一切顺利。

于 2013-12-01T15:00:05.737 回答
0

这要容易得多。只需将以下目标添加到您的构建文件或 Visual Studio 项目中

  <Target Name="AfterRebuild">
    <Message Text="AFTER REBUILD" Importance="High" />
    <!-- 
        Do whatever Needs to be done on Rebuild - as the message shows in VS Output 
        window it is only executed when an explicit rebuild is triggered  
    -->
  </Target>

如果您想要一个两步解决方案,请将其用作模板:

  <PropertyGroup>
    <IsRebuild>false</IsRebuild>
  </PropertyGroup>
  <Target Name="BeforeRebuild">
    <Message Text="BEFORE REBUILD" Importance="High" />
      <PropertyGroup>
        <IsRebuild>true</IsRebuild>
      </PropertyGroup>
  </Target>
  <Target Name="BeforeBuild">
    <Message Text="BEFORE BUILD: IsRebuild: $(IsRebuild)" Importance="High" />
  </Target>
于 2014-07-10T07:38:51.847 回答