将 PreBuildEvent 转换为具有条件的目标?

Convert a PreBuildEvent to a Target with a Condition?

我有一个名为 cryptdll.vcxproj 的项目。 cryptdll 依赖于解决方案中其他两个项目的工件。其他项目是 cryptlibcryptest。对于那些对 cryptdll 中的元素布局感兴趣的人,它位于 cryptdll.

依赖关系有些不寻常,在 Visual Studio 编辑器中不容易表达。它们很不寻常,因为策略要求 Win32\Output\Debug\cryptest.exe 始终用于执行 PostBuildEvent cryptdll.

我发现我可以将以下内容添加到 cryptdll 以使事情按预期工作:

<!-- Win32/Debug cryptest.exe for DLL MAC'ing -->
<ItemDefinitionGroup Condition="!Exists('Win32\Output\Debug\cryptest.exe')" Label="MAC tool">
  <PreBuildEvent>
    <Message>Creating Win32/Debug cryptest.exe for MAC computation</Message>
    <Command>
      msbuild /t:Build /p:Configuration=Debug;Platform=Win32 cryptlib.vcxproj
      msbuild /t:Build /p:Configuration=Debug;Platform=Win32 cryptest.vcxproj
    </Command>
  </PreBuildEvent>
</ItemDefinitionGroup>

当我试图将其转换为目标时,它停止了工作。下面是目标规则。

<!-- Win32/Debug cryptest.exe for DLL MAC'ing -->
<Target Condition="!Exists('Win32\Output\Debug\cryptest.exe')" Name="MAC tool" Label="MAC tool">
  <MSbuild
    Projects="cryptlib.vcxproj"
    Properties="Configuration=Debug;Platform=Win32;"/>
  <MSbuild
    Projects="cryptest.vcxproj"
    Properties="Configuration=Debug;Platform=Win32;"/>
</Target>

我的问题是,转换为 Target 的代码有什么问题,我该如何解决?


为了完整起见,我希望 Makefile 人员所说的 Prerequisite. The best I can tell from searching, every result for "MSBuild prerequisite" 无关紧要。


这是 Target 的输出结果。请注意,该任务被跳过,就好像它不存在一样。

>del /q /s Win32 x64
...

>msbuild /t:build /p:Configuration=Release;Platform=x64 cryptdll.vcxproj
Microsoft (R) Build Engine version 4.6.1055.0

Build started 10/6/2016 11:40:26 AM.
Project "c:\cryptopp\cryptdll.vcxproj" on node 1 (build target(s)).
PrepareForBuild:
  Creating directory "x64\cryptdll\Release\".
  Creating directory "x64\DLL_Output\Release\".
InitializeBuildStatus:
  Creating "x64\cryptdll\Release\cryptdll.unsuccessfulbuild" because "AlwaysCre
  ate" was specified.
CustomBuild:
  Performing Custom Build Tools
   Assembling: c:\cryptopp\x64dll.asm
ClCompile:
  c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\AMD64\CL.exe /c /Z
  i /nologo /W4 /WX- /O2 /Ob2 /Oi /Oy /D NDEBUG /D CRYPTOPP_EXPORTS /D CRYPTOPP
  _ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /D USE_PRECOMPILED_HEADERS /D _WINDLL /G
  F /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Yc"pch.h" /Fp"
  x64\cryptdll\Release\cryptopp.pch" /Fo"x64\cryptdll\Release\" /Fd"x64\cryptd
  ll\Release\vc100.pdb" /Gd /TP /errorReport:none pch.cpp
  pch.cpp
  ...

  <rest of the DLL is built>

PostBuildEvent:
  Description: Adding MAC to DLL

          Win32\output\debug\cryptest.exe mac_dll "cryptopp\x64\DLL_Output\Rele
  ase\cryptopp.dll"
          IF %ERRORLEVEL% EQU 0 (echo mac done > "x64\DLL_Output\Release\"\cryp
  topp.mac.done)

  :VCEnd
  The system cannot find the path specified.
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(1
13,5): error MSB3073: The command "\r [c:\cryptopp\cryptdll.vcxproj]
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(1
13,5): error MSB3073:         Win32\output\debug\cryptest.exe mac_dll "c:\crypt
opp\x64\DLL_Output\Release\cryptopp.dll"\r [c:\cryptopp\cryptdll.vcxproj]
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(1
13,5): error MSB3073:         IF %ERRORLEVEL% EQU 0 (echo mac done > "x64\DLL_O
utput\Release\"\cryptopp.mac.done)\r [c:\cryptopp\cryptdll.vcxproj]
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(1
13,5): error MSB3073:       \r [c:\cryptopp\cryptdll.vcxproj]
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(1
13,5): error MSB3073: :VCEnd" exited with code 3. [c:\cryptopp\cryptdll.vcxproj
Done Building Project "c:\cryptopp\cryptdll.vcxproj" (build target(s)) -- FAILE
D.

Build FAILED.

当我尝试将其转换为任务时你的意思是Target, that is not the same as a Task:第一个包含后者。

注意任务被跳过,就好像它不存在一样。好吧,你不会在任何地方告诉 msbuild 如何处理目标,所以它不可能知道何时调用它.您希望在构建之前调用它,因此您必须以某种方式表达它。在这里,BeforeTargets 属性(上面相同 link 中的文档)是规范的方式:

<Target Condition="!Exists('Win32\Output\Debug\cryptest.exe')"
        Name="MAC tool"
        BeforeTargets="Build">

旁注:为什么要为只是重复名称的目标添加标签?