Can I view what build commands are actually executed with MSBuild?
I use MSBuild to build the project file. By default, MSBuild just prints out the compilation results, bu开发者_运维技巧t I need to check what commands are being executed.
Can I view what build commands are actually executed? I want to check the compiler options and references are used with csc
command.
You can use the /v[erbosity] flag. I don't know that you can get a list of the flags passed to CSC, but if you use /v:Detailed or /v:diagnostic it will dump a ton of information about the targets being executed, all the MSBuild variables and their values, and all of the resolved reference assemblies.
[edit:] if you hunt for it, it looks like it will show you the command line call to csc.exe as well, even on /v:detailed.
You can set the output of a Visual Studio build to be detailed. Go to menu Tools -> Options -> Projects and Solutions -> Build and Run. Change the MSBuild project build output verbosity option, typically from the default Minimal to Normal, Detailed or Diagnostic.
- From Visual Studio 2019 Command Prompt,
- cd directory_containing_my_sln,
- Delete all object files and executables, if there are any, because MSBUILD might not recompile if you don't
- msbuild /v:normal > msbuild.log
- Observe that msbuild.log contains CLCompile and 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
The most fine-grained way to control this on the console is with
-consoleLoggerParameters:ShowCommandLine
aka -clp:ShowCommandLine
. As the docs explain, for VS2019:
The default console logger is at normal verbosity and includes a Summary.
(Summary
is also a type of output that can be printed or not, in the same class of things as ShowCommandLine
)
As it turned out (see experiments below with VS 2019), the minimal -v:m
verbosity level suppressed both stdout output from tools, except the msbuild banner, and supressed cmd echo.
At normal and above verbosity both cmd echo and tool stdout is printed with VS 2019. But you can get echo added back to -v:m
by adding -clp:ShowCommandLine
. This actually prints substantially less chatter than normal msbuild verbose level, especially from msbuild itself. Alas you cannot combine -clp:ShowCommandLine
with -v:q
, to supress the tools' banner but get the cmd echoed; -v:q
will still print the banner but nix the effect of -clp:ShowCommandLine
.
I don't build C# projects much myself, but the comment under the question (by user202729 Feb 25 '18 at 15:35) is correct that msbuild, at least the one from VS2019, will output the cmd line on the normal verbosity level.
I tested using the minimal msbuild C# example provided by MS, ran from the x64 dev cmd prompt:
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
It's possible that some VS-generated build files might override the implicit defaults. For the record, in case MS changes that example, the csproj file is:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="helloworld.cs" />
</ItemGroup>
<Target Name="Build">
<Csc Sources="@(Compile)"/>
</Target>
</Project>
I cannot quite find documented what precise sets of output thingies are included in each verbosity level though. There's a Q here about that, but present answers there just repeat what MS docs say, which is not detailed enough on this.
One thing that people have discovered is that stdout messages from tools invoked by msbuild are suppressed at the minimal verbosity level, but printed at normal and above. So, I guessed that minimal would also suppress cmd echo... and it does:
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>
So, you can actually get cmd echo but no other msbuild chatter, except errors and the msbuild banner, by using -v:m -clp:ShowCommandLine
:
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
Alas you cannot combine -clp:ShowCommandLine
with -v:q
, to suppress the banner but get the cmd echoed; -v:q
will still print the banner but nix the effect of -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>
You can suppress the msbuild banner separately with -nologo
, so -v:m -clp:ShowCommandLine -nologo
is a valid combo.
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>
Testing the minimal-ish native CPP example (which was of more interest to me), I get similar output, meaning the command line is printed by default.
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
I'm not pasting that .vcxproj
file here since it's a fair bit longer.
This fairly verbose output (including the cmd line) is certainly not the experience I had with such files generated from typical cmake projects, although after a bit of testing the latter, cmake defaults use... msbuild default verbosity, so include cmd echo. I'm sparing you the (even longer) output paste here from the build via the cmake-generated vcxproj, but you can see it on https://pastebin.com/WQtbYeDE. That was for a minimal CMakeLists.txt made for the previous MS C++ example.
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial main.cpp)
Also, it made no difference (verbosity wise) whether I msbuild the cmake-generated .sln
instead of the cmake-generated .vcxproj
more directly.
TLDR: nowadays with msbuild you have to turn cmd echo off rather than on; the default is on for most workflows. I haven't tested the VS IDE generated files in that (cmd echo) regard, though.
精彩评论