我可以查看使用 MSBuild 实际执行的构建命令吗?

Posted

技术标签:

【中文标题】我可以查看使用 MSBuild 实际执行的构建命令吗?【英文标题】:Can I view what build commands are actually executed with MSBuild? 【发布时间】:2011-06-16 14:48:13 【问题描述】:

我使用 MSBuild 来构建项目文件。 默认情况下,MSBuild 只是打印编译结果,但我需要检查正在执行的命令。

我可以查看实际执行了哪些构建命令吗?我想检查编译器选项和引用是否与csc 命令一起使用。

【问题讨论】:

对我来说,msbuild 默认打印所有csc 命令。 【参考方案1】:

您可以使用 /v[erbosity] 标志。我不知道您是否可以获得传递给 CSC 的标志列表,但如果您使用 /v:Detailed 或 /v:diagnostic,它将转储大量有关正在执行的目标、所有 MSBuild 变量及其值,以及所有已解析的引用程序集。

[edit:] 如果你寻找它,它看起来也会显示对 csc.exe 的命令行调用,即使在 /v:detailed 上也是如此。

【讨论】:

【参考方案2】:

您可以将 Visual Studio 构建的输出设置为详细。 转到菜单工具 -> 选项 -> 项目和解决方案 -> 构建和运行。更改 MSBuild 项目构建输出详细程度选项,通常从默认的 Minimal 更改为 Normal、Detailed 或 Diagnostic。

【讨论】:

【参考方案3】:
    来自 Visual Studio 2019 命令提示符, cd 目录_包含_my_sln, 删除所有对象文件和可执行文件(如果有),因为如果不这样做,MSBUILD 可能不会重新编译 msbuild /v:normal > msbuild.log 观察 msbuild.log 包含 CLCompile 和 Link:
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x64\CL.exe /c /IC:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\src /IC:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\..\pdelib\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\core\include /IC:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\..\pdelib\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\step\include /IC:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\..\pdelib\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\iges\include /ZI /JMC /nologo /W3 /WX- /diagnostics:column /sdl /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /RTC1 /MD /GS /fp:precise /permissive- /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"x64\Debug\\" /Fd"x64\Debug\vc142.pdb" /external:W3 /Gd /TP /FC /errorReport:queue /wd4996 /wd4703 ..\..\src\test_pdelib.cpp ..\..\src\test_step.cpp
  test_pdelib.cpp
  test_step.cpp
  Generating Code...
Link:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX86\x64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\x64\Debug\test_pdelib.exe" /INCREMENTAL /ILK:"x64\Debug\test_pdelib.ilk" /NOLOGO /LIBPATH:C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\core\lib /LIBPATH:C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\step\lib /LIBPATH:C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\..\..\..\pdelib_v7.8.3\v7.8.3\msdos_mcn\vc140_64_md\iges\lib libgdx.lib libpdx.lib libstep.lib libiges.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\x64\Debug\test_pdelib.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\x64\Debug\test_pdelib.lib" /MACHINE:X64 x64\Debug\test_pdelib.obj
  x64\Debug\test_step.obj
  test_pdelib.vcxproj -> C:\Users\Administrator\Desktop\pdelib\test_pdelib\v7.8.3\VSE2019.16.11.4\x64\Debug\test_pdelib.exe

【讨论】:

-fl 也会写入日志。默认名称是 msbuild.log :-) 可以使用 -flp 更改名称/位置。您还可以为日志文件设置与控制台不同的详细程度,例如-flp:LogFile=msbuild-detailed.log;Verbosity=diagnostic.【参考方案4】:

在控制台上控制它的最细粒度的方法是使用

-consoleLoggerParameters:ShowCommandLine

又名-clp:ShowCommandLine。作为文档explain, for VS2019:

默认控制台记录器处于正常冗长状态并包含摘要。

Summary 也是一种可以打印或不打印的输出,与ShowCommandLine 属于同一类)

事实证明(请参阅下面的 VS 2019 实验),最小的 -v:m 详细级别抑制了工具的 stdout 输出(msbuild 横幅除外)和 cmd 回显。

在正常及以上详细度下,cmd echo 和 tool stdout 都使用 VS 2019 打印。但您可以通过添加 -clp:ShowCommandLine 将 echo 添加回 -v:m。这实际上比正常的 msbuild 详细级别打印出更少的喋喋不休,尤其是来自 msbuild 本身。唉,你不能将 -clp:ShowCommandLine-v:q 结合起来,以抑制工具的横幅,但让 cmd 得到回应; -v:q 仍然会打印横幅,但不会影响 -clp:ShowCommandLine 的效果。


我自己并没有构建太多 C# 项目,但问题下的评论(user202729 2018 年 2 月 25 日 15:35)是正确的,msbuild,至少来自 VS2019 的那个,将在正常的详细程度。

我使用最小的 msbuild C# 示例 provided by MS 进行了测试,从 x64 开发 cmd 提示符运行:

M:\tests\cs-build>msbuild helloworld.csproj -t:Build
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 1/16/2022 9:42:20 AM.
Project "M:\tests\cs-build\helloworld.csproj" on node 1 (Build target(s)).
Build:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current
  \Bin\Roslyn\csc.exe /out:Helloworld.exe Helloworld.cs
  CompilerServer: tool - using command line tool by design 'C:\Program Files (x
  86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe
  ' - 753a030a-3ca4-43b9-9e98-18d923493186
Done Building Project "M:\tests\cs-build\helloworld.csproj" (Build target(s)).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.80

某些 VS 生成的构建文件可能会覆盖隐式默认值。作为记录,如果 MS 更改该示例,csproj 文件为:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Compile Include="helloworld.cs" />
  </ItemGroup>
  <Target Name="Build">
    <Csc Sources="@(Compile)"/>  
  </Target>
</Project>

我无法完全找到记录在每个详细级别中包含哪些精确的输出内容集。有一个Q here 对此进行了讨论,但目前的答案只是重复了 MS 文档所说的内容,这还不够详细。

人们have discovered 的一件事是,来自 msbuild 调用的工具的 stdout 消息在最小详细级别被抑制,但在正常及更高级别打印。所以,我猜最小也会抑制 cmd echo ......而且确实如此:

M:\tests\cs-build>msbuild helloworld.csproj -t:Build -v:m
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.


M:\tests\cs-build>

因此,您实际上可以通过使用-v:m -clp:ShowCommandLine 获得 cmd echo 但没有其他 msbuild 喋喋不休,除了错误和 msbuild 横幅:

M:\tests\cs-build>msbuild helloworld.csproj -t:Build -v:m -clp:ShowCommandLine
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current
  \Bin\Roslyn\csc.exe /out:Helloworld.exe Helloworld.cs

唉,你不能将-clp:ShowCommandLine-v:q 结合起来,以抑制横幅但得到 cmd 回显; -v:q 仍会打印横幅,但不会影响 -clp:ShowCommandLine 的效果。

M:\tests\cs-build>msbuild helloworld.csproj -t:Build -v:q -clp:ShowCommandLine
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.


M:\tests\cs-build>

您可以使用 -nologo 单独抑制 msbuild 横幅,因此 -v:m -clp:ShowCommandLine -nologo 是一个有效的组合。

M:\tests\cs-build>msbuild helloworld.csproj -t:Build -v:m -nologo -clp:ShowCommandLine
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current
  \Bin\Roslyn\csc.exe /out:Helloworld.exe Helloworld.cs

M:\tests\cs-build>

测试minimal-ish native CPP example(我更感兴趣),我得到了类似的输出,这意味着默认情况下会打印命令行。

M:\tests\cpp-build>msbuild myproject.vcxproj /p:configuration=debug
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 1/16/2022 10:05:01 AM.
Project "M:\tests\cpp-build\myproject.vcxproj" on node 1 (default targets).
InitializeBuildStatus:
  Touching "debug\myproject.tlog\unsuccessfulbuild".
ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\1
  4.29.30133\bin\HostX86\x86\CL.exe /c /Zi /nologo /W1 /WX- /diagnostics:column
   /O2 /Oy- /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline
  /Fo"debug\\" /Fd"debug\vc142.pdb" /external:W1 /Gd /TP /analyze- /FC /errorRe
  port:queue main.cpp
  main.cpp
Link:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\1
  4.29.30133\bin\HostX86\x86\link.exe /ERRORREPORT:QUEUE /OUT:"M:\tests\cpp-bui
  ld\debug\myproject.exe" /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.li
  b comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc3
  2.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'
  " /manifest:embed /DEBUG:FULL /PDB:"M:\tests\cpp-build\debug\myproject.pdb" /
  TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"M:\tests\cpp-build\debug\myproject.li
  b" /MACHINE:X86 /SAFESEH debug\main.obj
  myproject.vcxproj -> M:\tests\cpp-build\debug\myproject.exe
FinalizeBuildStatus:
  Deleting file "debug\myproject.tlog\unsuccessfulbuild".
  Touching "debug\myproject.tlog\myproject.lastbuildstate".
Done Building Project "M:\tests\cpp-build\myproject.vcxproj" (default targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.32

我不会在此处粘贴 .vcxproj 文件,因为它要长一些。

这个相当冗长的输出(包括 cmd 行)肯定不是我从典型 cmake 项目生成的此类文件的经验,尽管在对后者进行了一些测试后,cmake 默认使用... msbuild 默认冗长,所以包括cmd回显。我通过 cmake 生成的 vcxproj 从构建中为您节省了(甚至更长的)输出粘贴,但您可以在 https://pastebin.com/WQtbYeDE 上看到它。这是为之前的 MS C++ 示例制作的最小 CMakeLists.txt。

cmake_minimum_required(VERSION 3.10)

# set the project name
project(Tutorial)

# add the executable
add_executable(Tutorial main.cpp)

此外,我是否更直接地 msbuild 生成 cmake 生成的 .sln 而不是 cmake 生成的 .vcxproj 也没有区别。

TLDR:现在使用 msbuild 您必须关闭而不是打开 cmd echo;大多数工作流程的默认设置是打开的。不过,我还没有在(cmd echo)方面测试过 VS IDE 生成的文件。

【讨论】:

以上是关于我可以查看使用 MSBuild 实际执行的构建命令吗?的主要内容,如果未能解决你的问题,请参考以下文章

MSBuild:是不是可以在实际项目文件中指定项目构建依赖项?

如何找出Visual Studio发送给MSBuild的命令?

MsBuild 找不到发布配置文件

如何使用 msbuild 发布网页?

msbuild 只部署而不构建

如何使用msbuild首先构建依赖项目