Improve buildtest.cmd, runtest.cmd
authorBruce Forstall <brucefo@microsoft.com>
Fri, 8 Jan 2016 00:42:04 +0000 (16:42 -0800)
committerBruce Forstall <brucefo@microsoft.com>
Fri, 8 Jan 2016 00:42:04 +0000 (16:42 -0800)
Apply the same kind of changes that were applied to build.cmd:
1. Improved readability and structure of the code.
2. Make all three look similar.
3. Add "sequential" and "msbuildargs" options
4. Add better logging and less verbose console output

build.cmd
tests/buildtest.cmd
tests/runtest.cmd

index 40b142b..8f0d8ed 100644 (file)
--- a/build.cmd
+++ b/build.cmd
@@ -422,18 +422,32 @@ REM === Test build section
 REM ===
 REM =========================================================================================
 
-:PerformTestBuild
 if defined __SkipTestBuild (
     echo %__MsgPrefix%Skipping test build
     goto SkipTestBuild
 )
 
+if /i not "%__BuildArch%" == "x64" (
+    echo %__MsgPrefix%Skipping test build: architecture %__BuildArch% not supported for test build.
+    goto SkipTestBuild
+)
+
 echo %__MsgPrefix%Commencing build of tests for %__BuildOS%.%__BuildArch%.%__BuildType%
 
-set __BuildtestArgs=
+REM Construct the arguments to pass to the test build script.
+
+set __BuildtestArgs=%__BuildArch% %__BuildType% %__VSVersion%
+
+if defined __CleanBuild (
+    set "__BuildtestArgs=%__BuildtestArgs% clean"
+)
+
+if defined __BuildSequential (
+    set "__BuildtestArgs=%__BuildtestArgs% sequential"
+)
 
 if defined __TestPriority (
-    set "__BuildtestArgs=Priority %__TestPriority%"
+    set "__BuildtestArgs=%__BuildtestArgs% Priority %__TestPriority%"
 )
 
 call %__ProjectDir%\tests\buildtest.cmd %__BuildtestArgs%
index 5e434a8..c872f37 100644 (file)
-@echo off
+@if not defined __echo @echo off
 setlocal EnableDelayedExpansion
 
+:: Set the default arguments for build
+set __BuildArch=x64
+set __BuildType=Debug
+set __BuildOS=Windows_NT
+
+:: Default to highest Visual Studio version available
+set __VSVersion=vs2015
+
+if defined VS120COMNTOOLS set __VSVersion=vs2013
+if defined VS140COMNTOOLS set __VSVersion=vs2015
+
+:: Define a prefix for most output progress messages that come from this script. That makes
+:: it easier to see where these are coming from. Note that there is a trailing space here.
+set __MsgPrefix=BUILDTEST: 
+
 set "__ProjectDir=%~dp0..\"
 :: remove trailing slash
 if %__ProjectDir:~-1%==\ set "__ProjectDir=%__ProjectDir:~0,-1%"
-set "__SourceDir=%__ProjectDir%\src"
 set "__TestDir=%__ProjectDir%\tests"
 set "__ProjectFilesDir=%__TestDir%"
+set "__SourceDir=%__ProjectDir%\src"
 set "__PackagesDir=%__ProjectDir%\packages"
 set "__RootBinDir=%__ProjectDir%\bin"
 set "__LogsDir=%__RootBinDir%\Logs"
 
-:: Default to highest Visual Studio version available
-if not defined __VSVersion (
-    set __VSVersion=vs2015
-
-    if defined VS120COMNTOOLS set __VSVersion=vs2013
-    if defined VS140COMNTOOLS set __VSVersion=vs2015
-)
+set __CleanBuild=
+set __crossgen=
+set __ILAsmRoundtrip=
+set __BuildSequential=
+set __TestPriority=
+set __msbuildCleanBuildArgs=
+set __msbuildExtraArgs=
+set __verbosity=normal
 
 :Arg_Loop
 if "%1" == "" goto ArgsDone
-if /i "%1" == "x64"    (set __BuildArch=x64&shift&goto Arg_Loop)
 
-if /i "%1" == "debug"    (set __BuildType=Debug&shift&goto Arg_Loop)
-if /i "%1" == "release"   (set __BuildType=Release&shift&goto Arg_Loop)
-if /i "%1" == "checked"   (set __BuildType=Checked&shift&goto Arg_Loop)
+if /i "%1" == "/?"    goto Usage
+if /i "%1" == "-?"    goto Usage
+if /i "%1" == "/h"    goto Usage
+if /i "%1" == "-h"    goto Usage
+if /i "%1" == "/help" goto Usage
+if /i "%1" == "-help" goto Usage
 
-if /i "%1" == "clean"   (set __CleanBuild=1&shift&goto Arg_Loop)
+if /i "%1" == "x64"                 (set __BuildArch=x64&shift&goto Arg_Loop)
 
-if /i "%1" == "vs2013"   (set __VSVersion=%1&shift&goto Arg_Loop)
-if /i "%1" == "vs2015"   (set __VSVersion=%1&shift&goto Arg_Loop)
+if /i "%1" == "debug"               (set __BuildType=Debug&shift&goto Arg_Loop)
+if /i "%1" == "release"             (set __BuildType=Release&shift&goto Arg_Loop)
+if /i "%1" == "checked"             (set __BuildType=Checked&shift&goto Arg_Loop)
 
-if /i "%1" == "crossgen" (set _crossgen=true&shift&goto Arg_Loop)
-if /i "%1" == "ilasmroundtrip" (set _ilasmroundtrip=true&shift&goto Arg_Loop)
-if /i "%1" == "priority" (set _priorityvalue=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "clean"               (set __CleanBuild=1&shift&goto Arg_Loop)
 
-if /i "%1" == "verbose" (set _verbosity=detailed&shift&goto Arg_Loop)
+if /i "%1" == "vs2013"              (set __VSVersion=%1&shift&goto Arg_Loop)
+if /i "%1" == "vs2015"              (set __VSVersion=%1&shift&goto Arg_Loop)
 
-goto Usage
+if /i "%1" == "crossgen"            (set __crossgen=true&shift&goto Arg_Loop)
+if /i "%1" == "ilasmroundtrip"      (set __ILAsmRoundtrip=true&shift&goto Arg_Loop)
+if /i "%1" == "sequential"          (set __BuildSequential=1&shift&goto Arg_Loop)
+if /i "%1" == "priority"            (set __TestPriority=%2&shift&shift&goto Arg_Loop)
+
+if /i "%1" == "verbose"             (set __verbosity=detailed&shift&goto Arg_Loop)
 
+if /i not "%1" == "msbuildargs" goto SkipMsbuildArgs
+:: All the rest of the args will be collected and passed directly to msbuild.
+:CollectMsbuildArgs
+shift
+if "%1"=="" goto ArgsDone
+set __msbuildExtraArgs=%__msbuildExtraArgs% %1
+goto CollectMsbuildArgs
+:SkipMsbuildArgs
+
+echo Invalid command-line argument: %1
+goto Usage
 
 :ArgsDone
 
-if defined _crossgen echo Building tests with CrossGen enabled.&set _buildParameters=%_buildParameters% /p:CrossGen=true
-if defined _ilasmroundtrip echo Building tests with IlasmRoundTrip enabled.&set _buildParameters=%_buildParameters% /p:IlasmRoundTrip=true
-if defined _priorityvalue echo Building Test Priority %_priorityvalue%&set _buildParameters=%_buildParameters% /p:CLRTestPriorityToBuild=%_priorityvalue%
-if defined _verbosity echo Enabling verbose file logging
-if not defined _verbosity set _verbosity=normal
+if %__verbosity%==detailed (
+    echo Enabling verbose file logging
+)
 
-if not defined __BuildArch set __BuildArch=x64
-if not defined __BuildType set __BuildType=Debug
-if not defined __BuildOS set __BuildOS=Windows_NT
+echo %__MsgPrefix%Commencing CoreCLR repo test build
 
 set "__BinDir=%__RootBinDir%\Product\%__BuildOS%.%__BuildArch%.%__BuildType%"
 set "__TestBinDir=%__RootBinDir%\tests\%__BuildOS%.%__BuildArch%.%__BuildType%"
 :: We have different managed and native intermediate dirs because the managed bits will include
 :: the configuration information deeper in the intermediates path.
+:: These variables are used by the msbuild project files.
 set "__NativeTestIntermediatesDir=%__RootBinDir%\tests\obj\%__BuildOS%.%__BuildArch%.%__BuildType%"
 set "__ManagedTestIntermediatesDir=%__RootBinDir%\tests\obj"
-set "__TestManagedBuildLog=%__LogsDir%\Tests_Managed_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
-set "__TestNativeBuildLog=%__LogsDir%\Tests_Native_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
-set "__XunitWrapperBuildLog=%__LogsDir%\Tests_XunitWrapper_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
 
 :: Generate path to be set for CMAKE_INSTALL_PREFIX to contain forward slash
 set "__CMakeBinDir=%__TestBinDir%"
 set "__CMakeBinDir=%__CMakeBinDir:\=/%"
 
 :: Configure environment if we are doing a clean build.
-if not defined __CleanBuild goto MakeDirectories
-echo Doing a clean test build
-echo.
+if not defined __CleanBuild goto SkipCleanBuild
+echo %__MsgPrefix%Doing a clean test build
 
 :: MSBuild projects would need a rebuild
-set __MSBCleanBuildArgs=/t:rebuild
+set __msbuildCleanBuildArgs=/t:rebuild
 
 :: Cleanup the binaries drop folder for the current configuration
-if exist "%__TestBinDir%" rd /s /q "%__TestBinDir%"
-if exist "%__NativeTestIntermediatesDir%" rd /s /q "%__NativeTestIntermediatesDir%"
+if exist "%__TestBinDir%"                   rd /s /q "%__TestBinDir%"
+if exist "%__NativeTestIntermediatesDir%"   rd /s /q "%__NativeTestIntermediatesDir%"
 
-:MakeDirectories
-if not exist "%__TestBinDir%" md "%__TestBinDir%"
-if not exist "%__NativeTestIntermediatesDir%" md "%__NativeTestIntermediatesDir%"
-if not exist "%__ManagedTestIntermediatesDir%" md "%__ManagedTestIntermediatesDir%"
-if not exist "%__LogsDir%" md "%__LogsDir%"
+:SkipCleanBuild
 
-:: Note: We've disabled node reuse because it causes file locking issues.
-::       The issue is that we extend the build with our own targets which
-::       means that that rebuilding cannot successully delete the task
-::       assembly. 
+if not exist "%__TestBinDir%"                   md "%__TestBinDir%"
+if not exist "%__NativeTestIntermediatesDir%"   md "%__NativeTestIntermediatesDir%"
+if not exist "%__ManagedTestIntermediatesDir%"  md "%__ManagedTestIntermediatesDir%"
+if not exist "%__LogsDir%"                      md "%__LogsDir%"
+
+echo %__MsgPrefix%Checking prerequisites
 
-:: Check prerequisites
-:CheckPrereqs
-echo Checking pre-requisites...
-echo.
 :: Eval the output from probe-win1.ps1
 for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& ""%__SourceDir%\pal\tools\probe-win.ps1"""') do %%a
 
@@ -102,11 +123,16 @@ if /i "%__VSVersion%" == "vs2013" set __VSProductVersion=120
 if /i "%__VSVersion%" == "vs2015" set __VSProductVersion=140
 
 :: Check presence of VS
-if defined VS%__VSProductVersion%COMNTOOLS goto CheckMSBuild
-echo Visual Studio 2013+ (Community is free) is a pre-requisite to build this repository.
-exit /b 1
+if not defined VS%__VSProductVersion%COMNTOOLS goto NoVS
+
+set __VSToolsRoot=!VS%__VSProductVersion%COMNTOOLS!
+if %__VSToolsRoot:~-1%==\ set "__VSToolsRoot=%__VSToolsRoot:~0,-1%"
+
+:: Does VS really exist?
+if not exist "%__VSToolsRoot%\..\IDE\devenv.exe"      goto NoVS
+if not exist "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" goto NoVS
+if not exist "%__VSToolsRoot%\VsDevCmd.bat"           goto NoVS
 
-:CheckMSBuild
 if /i "%__VSVersion%" =="vs2015" goto MSBuild14
 set _msbuildexe="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe"
 if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles%\MSBuild\12.0\Bin\MSBuild.exe"
@@ -119,110 +145,194 @@ set UseRoslynCompiler=true
 if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles%\MSBuild\14.0\Bin\MSBuild.exe"
 if not exist %_msbuildexe% echo Error: Could not find MSBuild.exe.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. && exit /b 1
 
+:: Note: We've disabled node reuse because it causes file locking issues.
+::       The issue is that we extend the build with our own targets which
+::       means that that rebuilding cannot successfully delete the task
+::       assembly. 
+set __msbuildCommonArgs=/nologo /nodeReuse:false %__msbuildCleanBuildArgs% %__msbuildExtraArgs%
+
+if not defined __BuildSequential (
+    set __msbuildCommonArgs=%__msbuildCommonArgs% /maxcpucount
+)
+
+REM =========================================================================================
+REM ===
+REM === Native test build section
+REM ===
+REM =========================================================================================
+
 ::Building Native part of Tests
-setlocal
+setlocal EnableDelayedExpansion
 
-echo Commencing build of native test components for %__BuildArch%/%__BuildType%
-echo.
+echo %__MsgPrefix%Commencing build of native test components for %__BuildArch%/%__BuildType%
 
 :: Set the environment for the native build
-call "!VS%__VSProductVersion%COMNTOOLS!..\..\VC\vcvarsall.bat" x86_amd64
+echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" %__VCBuildArch%
+call                                 "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" x86_amd64
+@if defined __echo @echo on
 
-if exist "%VSINSTALLDIR%DIA SDK" goto GenVSSolution
-echo Error: DIA SDK is missing at "%VSINSTALLDIR%DIA SDK". ^
-This is due to bug in VS Intaller. It does not install DIA SDK at "%VSINSTALLDIR%" but rather ^
-at VS install location of previous version. Workaround is to copy DIA SDK folder from VS install location ^
-of previous version to "%VSINSTALLDIR%" and then resume build.
-exit /b 1
+if not defined VSINSTALLDIR (
+    echo %__MsgPrefix%Error: VSINSTALLDIR variable not defined.
+    exit /b 1
+)
+if not exist "%VSINSTALLDIR%DIA SDK" goto NoDIA
+
+echo %__MsgPrefix%Regenerating the Visual Studio solution
 
-:GenVSSolution
-:: Regenerate the VS solution
 pushd "%__NativeTestIntermediatesDir%"
 call "%__SourceDir%\pal\tools\gen-buildsys-win.bat" "%__ProjectFilesDir%\" %__VSVersion% %__BuildArch%
+@if defined __echo @echo on
 popd
 
-:BuildComponents
-if exist "%__NativeTestIntermediatesDir%\install.vcxproj" goto BuildTestNativeComponents
-echo Failed to generate test native component build project!
-exit /b 1
+if not exist "%__NativeTestIntermediatesDir%\install.vcxproj" (
+    echo %__MsgPrefix%Failed to generate test native component build project!
+    exit /b 1
+)
 
-REM Build CoreCLR
-:BuildTestNativeComponents
-%_msbuildexe% "%__NativeTestIntermediatesDir%\install.vcxproj" %__MSBCleanBuildArgs% /nologo /maxcpucount /nodeReuse:false /p:Configuration=%__BuildType% /p:Platform=%__BuildArch% /fileloggerparameters:Verbosity=%_verbosity%;LogFile="%__TestNativeBuildLog%"
-IF NOT ERRORLEVEL 1 goto PerformManagedTestBuild
-echo Native component build failed. Refer !__TestNativeBuildLog! for details.
-exit /b 1
+set __BuildLogRootName=Tests_Native
+call :msbuild "%__NativeTestIntermediatesDir%\install.vcxproj" /p:Configuration=%__BuildType% /p:Platform=%__BuildArch%
+if errorlevel 1 exit /b 1
 
-:PerformManagedTestBuild
 REM endlocal to rid us of environment changes from vcvarsall.bat
 endlocal
-::End Building native tests
 
-::Building Managed Tests
+REM =========================================================================================
+REM ===
+REM === Managed test build section
+REM ===
+REM =========================================================================================
+
 REM setlocal to prepare for vsdevcmd.bat
-setlocal
-:: Set the environment for the managed build- Vs cmd prompt
-call "!VS%__VSProductVersion%COMNTOOLS!\VsDevCmd.bat"
-if not defined VSINSTALLDIR echo Error: build.cmd should be run from a Visual Studio Command Prompt.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. && exit /b 1
+setlocal EnableDelayedExpansion
 
-:BuildTests
+echo %__MsgPrefix%Starting the Managed Tests Build
 
-echo Starting the Managed Tests Build
-echo.
-:: Log build command line
-set _buildprefix=echo
-set _buildpostfix=^> "%__TestManagedBuildLog%"
-set _buildappend=^>
-call :build %1
-
-:: Build
-set _buildprefix=
-set _buildpostfix=
-set _buildappend=
-call :build %1
-if ERRORLEVEL 1 exit /b 1
+:: Set the environment for the managed build
+echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\VsDevCmd.bat"
+call                                 "%__VSToolsRoot%\VsDevCmd.bat"
 
-set CORE_ROOT=%__TestBinDir%\Tests\Core_Root
-echo.
-echo Creating test overlay...
+if not defined VSINSTALLDIR (
+    echo %__MsgPrefix%Error: buildtest.cmd should be run from a Visual Studio Command Prompt.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions.
+    exit /b 1
+)
 
-:: Log build command line
-set _buildprefix=echo
-set _buildpostfix=^> "%__TestManagedBuildLog%"
-set _buildappend=^>
-call :CreateTestOverlay %1
+set __msbuildManagedBuildArgs=
 
-:: Build
-set _buildprefix=
-set _buildpostfix=
-set _buildappend=
-call :CreateTestOverlay %1
+if defined __crossgen (
+    echo Building tests with CrossGen enabled.
+    set __msbuildManagedBuildArgs=%__msbuildManagedBuildArgs% /p:CrossGen=true
+)
+
+if defined __ILAsmRoundtrip (
+    echo Building tests with IlasmRoundTrip enabled.
+    set __msbuildManagedBuildArgs=%__msbuildManagedBuildArgs% /p:IlasmRoundTrip=true
+)
+
+if defined __TestPriority (
+    echo Building Test Priority %__TestPriority%
+    set __msbuildManagedBuildArgs=%__msbuildManagedBuildArgs% /p:CLRTestPriorityToBuild=%__TestPriority%
+)
+
+set __BuildLogRootName=Tests_Managed
+call :msbuild "%__ProjectFilesDir%\build.proj" %__msbuildManagedBuildArgs%
+if errorlevel 1 exit /b 1
+
+set CORE_ROOT=%__TestBinDir%\Tests\Core_Root
 
-exit /b %ERRORLEVEL%
+echo %__MsgPrefix%Creating test overlay...
 
-:build
+set __BuildLogRootName=Tests_Overlay_Managed
+call :msbuild "%__ProjectFilesDir%\runtest.proj" /t:CreateTestOverlay
+if errorlevel 1 exit /b 1
 
-%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%\build.proj" %__MSBCleanBuildArgs% /nologo /maxcpucount /verbosity:minimal /nodeReuse:false %_buildParameters% /fileloggerparameters:Verbosity=%_verbosity%;LogFile="%__TestManagedBuildLog%";Append %* %_buildpostfix%
-IF ERRORLEVEL 1 echo Test build failed. Refer to !__TestManagedBuildLog! for details && exit /b 1
+REM =========================================================================================
+REM ===
+REM === All builds complete!
+REM ===
+REM =========================================================================================
+
+echo %__MsgPrefix%Test build successful.
+echo %__MsgPrefix%Test binaries are available at !__TestBinDir!
 exit /b 0
 
-:CreateTestOverlay
+REM =========================================================================================
+REM ===
+REM === Helper routines
+REM ===
+REM =========================================================================================
+
+:msbuild
+@REM Subroutine to invoke msbuild. All arguments are passed to msbuild. The first argument should be the
+@REM .proj file to invoke.
+@REM
+@REM On entry, __BuildLogRootName must be set to a file name prefix for the generated log file.
+@REM All the "standard" environment variables that aren't expected to change per invocation must also be set,
+@REM like __msbuildCommonArgs.
+@REM
+@REM The build log files will be overwritten, not appended to.
+
+echo %__MsgPrefix%Invoking msbuild
+
+set "__BuildLog=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
+set "__BuildWrn=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn"
+set "__BuildErr=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.err"
+
+set __msbuildLogArgs=^
+/fileloggerparameters:Verbosity=%__verbosity%;LogFile="%__BuildLog%";Append ^
+/fileloggerparameters1:WarningsOnly;LogFile="%__BuildWrn%" ^
+/fileloggerparameters2:ErrorsOnly;LogFile="%__BuildErr%" ^
+/consoleloggerparameters:Summary ^
+/verbosity:minimal
+
+set __msbuildArgs=%* %__msbuildCommonArgs% %__msbuildLogArgs%
+
+@REM The next line will overwrite the existing log file, if any.
+echo Invoking: %_msbuildexe% %__msbuildArgs% > "%__BuildLog%"
+
+%_msbuildexe% %__msbuildArgs%
+if errorlevel 1 (
+    echo %__MsgPrefix%Error: build failed. Refer to the build log files for details:
+    echo     %__BuildLog%
+    echo     %__BuildWrn%
+    echo     %__BuildErr%
+    exit /b 1
+)
 
-%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%\runtest.proj" /t:CreateTestOverlay /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=%_verbosity%;LogFile="%__TestManagedBuildLog%";Append %* %_buildpostfix%
-IF ERRORLEVEL 1 echo Failed to create the test overlay. Refer to !__TestManagedBuildLog! for details && exit /b 1
 exit /b 0
 
 :Usage
 echo.
 echo Usage:
-echo %0 BuildArch BuildType [clean] [vsversion] [crossgen] [priority N] [verbose] where:
+echo     %0 [option1] [option2] ...
+echo All arguments are optional. Options are case-insensitive. The options are:
 echo.
-echo BuildArch can be: x64
-echo BuildType can be: Debug, Release, Checked
-echo Clean - optional argument to force a clean build.
-echo VSVersion - optional argument to use VS2013 or VS2015  (default VS2015)
-echo CrossGen - Enables the tests to run crossgen on the test executables before executing them. 
-echo Priority (N) where N is a number greater than zero that signifies the set of tests that will be built and consequently run.
-echo IlasmRoundTrip - Enables ilasm round trip build and run of the tests before executing them.
-echo Verbose - Enables detailed file logging for the msbuild tasks.
+echo./? -? /h -h /help -help: view this message.
+echo Build architecture: only x64 is currently allowed ^(default: x64^).
+echo Build type: one of Debug, Checked, Release ^(default: Debug^).
+echo Visual Studio version: one of VS2013 or VS2015 to force using a particular
+echo     Visual Studio version ^(default: VS2015^).
+echo clean: force a clean build ^(default is to perform an incremental build^).
+echo CrossGen: enables the tests to run crossgen on the test executables before executing them. 
+echo msbuildargs ... : all arguments following this tag will be passed directly to msbuild.
+echo priority ^<N^> : specify a set of test that will be built and run, with priority N.
+echo sequential: force a non-parallel build ^(default is to build in parallel
+echo     using all processors^).
+echo IlasmRoundTrip: enables ilasm round trip build and run of the tests before executing them.
+echo verbose: enables detailed file logging for the msbuild tasks into the msbuild log file.
+exit /b 1
+
+:NoVS
+echo Visual Studio 2013+ ^(Community is free^) is a prerequisite to build this repository.
+echo See: https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md#prerequisites
+exit /b 1
+
+:NoDIA
+echo Error: DIA SDK is missing at "%VSINSTALLDIR%DIA SDK". ^
+This is due to a bug in the Visual Studio installer. It does not install DIA SDK at "%VSINSTALLDIR%" but rather ^
+at the install location of previous Visual Studio version. The workaround is to copy the DIA SDK folder from the Visual Studio install location ^
+of the previous version to "%VSINSTALLDIR%" and then build.
+:: DIA SDK not included in Express editions
+echo Visual Studio 2013 Express does not include the DIA SDK. ^
+You need Visual Studio 2013+ (Community is free).
+echo See: https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md#prerequisites
 exit /b 1
index 0f92eb2..d564fa1 100644 (file)
@@ -1,6 +1,10 @@
-@echo off
+@if not defined __echo @echo off
 setlocal EnableDelayedExpansion
-set __ProjectFilesDir=%~dp0
+
+:: Set the default arguments
+set __BuildArch=x64
+set __BuildType=Debug
+set __BuildOS=Windows_NT
 
 :: Default to highest Visual Studio version available
 set __VSVersion=vs2015
@@ -8,42 +12,89 @@ set __VSVersion=vs2015
 if defined VS120COMNTOOLS set __VSVersion=vs2013
 if defined VS140COMNTOOLS set __VSVersion=vs2015
 
+:: Define a prefix for most output progress messages that come from this script. That makes
+:: it easier to see where these are coming from. Note that there is a trailing space here.
+set __MsgPrefix=RUNTEST: 
+
+set __ProjectDir=%~dp0
+:: remove trailing slash
+if %__ProjectDir:~-1%==\ set "__ProjectDir=%__ProjectDir:~0,-1%"
+set "__ProjectFilesDir=%__ProjectDir%"
+set "__RootBinDir=%__ProjectDir%\..\bin"
+set "__LogsDir=%__RootBinDir%\Logs"
+
 :: Default __Exclude to issues.targets
 set __Exclude0=%~dp0\issues.targets
 
+set __BuildSequential=
+set __msbuildExtraArgs=
+
 :Arg_Loop
 if "%1" == "" goto ArgsDone
-if /i "%1" == "x64"    (set __BuildArch=x64&set __MSBuildBuildArch=x64&shift&goto Arg_Loop)
-if /i "%1" == "x86"    (set __BuildArch=x86&set __MSBuildBuildArch=x86&shift&goto Arg_Loop)
 
-if /i "%1" == "debug"    (set __BuildType=debug&shift&goto Arg_Loop)
-if /i "%1" == "release"   (set __BuildType=release&shift&goto Arg_Loop)
-if /i "%1" == "checked"   (set __BuildType=checked&shift&goto Arg_Loop)
-if /i "%1" == "SkipWrapperGeneration" (set __SkipWrapperGeneration=true&shift&goto Arg_Loop)
-if /i "%1" == "Exclude" (set __Exclude=%2&shift&shift&goto Arg_Loop)
-if /i "%1" == "Exclude0" (set __Exclude0=%2&shift&shift&goto Arg_Loop)
-if /i "%1" == "TestEnv" (set __TestEnv=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "/?"    goto Usage
+if /i "%1" == "-?"    goto Usage
+if /i "%1" == "/h"    goto Usage
+if /i "%1" == "-h"    goto Usage
+if /i "%1" == "/help" goto Usage
+if /i "%1" == "-help" goto Usage
+
+if /i "%1" == "x64"                 (set __BuildArch=x64&set __MSBuildBuildArch=x64&shift&goto Arg_Loop)
+if /i "%1" == "x86"                 (set __BuildArch=x86&set __MSBuildBuildArch=x86&shift&goto Arg_Loop)
+
+if /i "%1" == "debug"               (set __BuildType=Debug&shift&goto Arg_Loop)
+if /i "%1" == "release"             (set __BuildType=Release&shift&goto Arg_Loop)
+if /i "%1" == "checked"             (set __BuildType=Checked&shift&goto Arg_Loop)
 
-if /i "%1" == "vs2013" (set __VSVersion=%1&shift&goto Arg_Loop)
-if /i "%1" == "vs2015" (set __VSVersion=%1&shift&goto Arg_Loop)
+if /i "%1" == "vs2013"              (set __VSVersion=%1&shift&goto Arg_Loop)
+if /i "%1" == "vs2015"              (set __VSVersion=%1&shift&goto Arg_Loop)
 
-if /i "%1" == "/?"      (goto Usage)
+if /i "%1" == "SkipWrapperGeneration" (set __SkipWrapperGeneration=true&shift&goto Arg_Loop)
+if /i "%1" == "Exclude"             (set __Exclude=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "Exclude0"            (set __Exclude0=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "TestEnv"             (set __TestEnv=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "sequential"          (set __BuildSequential=1&shift&goto Arg_Loop)
+
+if /i not "%1" == "msbuildargs" goto SkipMsbuildArgs
+:: All the rest of the args will be collected and passed directly to msbuild.
+:CollectMsbuildArgs
+shift
+if "%1"=="" goto ArgsDone
+set __msbuildExtraArgs=%__msbuildExtraArgs% %1
+goto CollectMsbuildArgs
+:SkipMsbuildArgs
 
 set CORE_ROOT=%1
 shift 
 :ArgsDone
-:: Check prerequisites
+
+:: Set the remaining variables based upon the determined configuration
+set "__BinDir=%__RootBinDir%\Product\%__BuildOS%.%__BuildArch%.%__BuildType%"
+set "__TestWorkingDir=%__RootBinDir%\tests\%__BuildOS%.%__BuildArch%.%__BuildType%"
+
+:: Default global test environment variables
+:: REVIEW: are these ever expected to be defined on entry to this script? Why? By whom?
+:: REVIEW: XunitTestReportDirBase is not used in this script. Who needs to have it set?
+if not defined XunitTestBinBase       set  XunitTestBinBase=%__TestWorkingDir%
+if not defined XunitTestReportDirBase set  XunitTestReportDirBase=%XunitTestBinBase%\Reports\
+
+if not exist %__LogsDir% md %__LogsDir%
 
 set __VSProductVersion=
 if /i "%__VSVersion%" == "vs2013" set __VSProductVersion=120
 if /i "%__VSVersion%" == "vs2015" set __VSProductVersion=140
 
 :: Check presence of VS
-if defined VS%__VSProductVersion%COMNTOOLS goto CheckMSbuild
-echo Visual Studio 2013+ (Community is free) is a pre-requisite to build this repository.
-exit /b 1
+if not defined VS%__VSProductVersion%COMNTOOLS goto NoVS
+
+set __VSToolsRoot=!VS%__VSProductVersion%COMNTOOLS!
+if %__VSToolsRoot:~-1%==\ set "__VSToolsRoot=%__VSToolsRoot:~0,-1%"
+
+:: Does VS really exist?
+if not exist "%__VSToolsRoot%\..\IDE\devenv.exe"      goto NoVS
+if not exist "%__VSToolsRoot%\..\..\VC\vcvarsall.bat" goto NoVS
+if not exist "%__VSToolsRoot%\VsDevCmd.bat"           goto NoVS
 
-:CheckMSBuild
 if /i "%__VSVersion%" =="vs2015" goto MSBuild14
 set _msbuildexe="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe"
 if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles%\MSBuild\12.0\Bin\MSBuild.exe"
@@ -57,110 +108,159 @@ if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles%\MSBuild\14.0\Bin\MSBu
 if not exist %_msbuildexe% echo Error: Could not find MSBuild.exe.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. && exit /b 1
 
 :: Set the environment for the  build- VS cmd prompt
-call "!VS%__VSProductVersion%COMNTOOLS!\VsDevCmd.bat"
-
-if not defined VSINSTALLDIR echo Error: runtest.cmd should be run from a Visual Studio Command Prompt.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions. && exit /b 1
+echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\VsDevCmd.bat"
+call                                 "%__VSToolsRoot%\VsDevCmd.bat"
 
+if not defined VSINSTALLDIR (
+    echo %__MsgPrefix%Error: runtest.cmd should be run from a Visual Studio Command Prompt.  Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions.
+    exit /b 1
+)
 
-if not defined __BuildArch set __BuildArch=x64
-if not defined __BuildType set __BuildType=debug
-if not defined __BuildOS set __BuildOS=Windows_NT
-if not defined __BinDir    set  __BinDir=%__ProjectFilesDir%..\bin\Product\%__BuildOS%.%__BuildArch%.%__BuildType%
-if not defined __TestWorkingDir set __TestWorkingDir=%__ProjectFilesDir%..\bin\tests\%__BuildOS%.%__BuildArch%.%__BuildType%
-if not defined __LogsDir        set  __LogsDir=%__ProjectFilesDir%..\bin\Logs
+:: Note: We've disabled node reuse because it causes file locking issues.
+::       The issue is that we extend the build with our own targets which
+::       means that that rebuilding cannot successfully delete the task
+::       assembly. 
+set __msbuildCommonArgs=/nologo /nodeReuse:false %__msbuildExtraArgs%
 
-:: Default global test environment variables
-if not defined XunitTestBinBase       set  XunitTestBinBase=%__TestWorkingDir%\
-if not defined XunitTestReportDirBase set  XunitTestReportDirBase=%XunitTestBinBase%\Reports\
-if defined CORE_ROOT goto  :CheckTestEnv 
+if not defined __BuildSequential (
+    set __msbuildCommonArgs=%__msbuildCommonArgs% /maxcpucount
+)
 
-set noCore_RootSet=true
-set CORE_ROOT=%__BinDir%
+if not defined CORE_ROOT (
+    set noCore_RootSet=true
+    set "CORE_ROOT=%__BinDir%"
+)
 
-:CheckTestEnv 
 ::Check if the test Binaries are built
-if not exist %XunitTestBinBase% echo Error: Ensure the Test Binaries are built and are present at %XunitTestBinBase%, Run - buildtest.cmd %__BuildArch% %__BuildType% to build the tests first. && exit /b 1
-if "%CORE_ROOT%" == ""             echo Error: Ensure you have done a successful build of the Product and Run - runtest BuildArch BuildType {path to product binaries}. && exit /b 1
-if not exist %CORE_ROOT%\coreclr.dll echo Error: Ensure you have done a successful build of the Product and %CORE_ROOT% contains runtime binaries. && exit /b 1
-if not "%__Exclude%"==""           (if not exist %__Exclude% echo Error: Exclusion .targets file not found && exit /b 1) 
-if not "%__TestEnv%"==""           (if not exist %__TestEnv% echo Error: Test Environment script not found && exit /b 1) 
-if not exist %__LogsDir%           md  %__LogsDir%
-
-:SkipDefaultCoreRootSetup
-set __XunitWrapperBuildLog=%__LogsDir%\Tests_XunitWrapper_%__BuildOS%__%__BuildArch%__%__BuildType%.log
-set __TestRunBuildLog=%__LogsDir%\TestRunResults_%__BuildOS%__%__BuildArch%__%__BuildType%.log
-set __TestRunHtmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.html
-set __TestRunXmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.xml
+if not exist %XunitTestBinBase% (
+    echo %__MsgPrefix%Error: Ensure the Test Binaries are built and are present at %XunitTestBinBase%.
+    echo %__MsgPrefix%Run "buildtest.cmd %__BuildArch% %__BuildType%" to build the tests first.
+    exit /b 1
+)
 
-echo CORE_ROOT that will be used is: %CORE_ROOT%
-echo Starting The Test Run ...
-if  "%__SkipWrapperGeneration%"=="true" goto :preptests
-
-:: Log build command line
-set _buildprefix=echo
-set _buildpostfix=^> "%__TestRunBuildLog%"
-set _buildappend=^>
-call :PerformXunitWrapperBuild 
-
-:: Build
-set _buildprefix=
-set _buildpostfix=
-set _buildappend=
-call :PerformXunitWrapperBuild 
-IF ERRORLEVEL 1 (
-    echo XunitWrapperBuild build failed. Refer %__XunitWrapperBuildLog% for details.
+if "%CORE_ROOT%" == "" (
+    echo %__MsgPrefix%Error: Ensure you have done a successful build of the Product and Run - runtest BuildArch BuildType {path to product binaries}.
     exit /b 1
 )
 
-:: Log build command line
-set _buildprefix=echo
-set _buildpostfix=^> "%__TestRunBuildLog%"
-set _buildappend=^>
-call :runtests
-
-:: Build
-set _buildprefix=
-set _buildpostfix=
-set _buildappend=
-if not "%noCore_RootSet%"=="true" goto :runtests 
-set CORE_ROOT=%XunitTestBinBase%\Tests\Core_Root
-echo Using Default CORE_ROOT as %CORE_ROOT%
-echo Copying Built binaries from  %__BinDir% to %CORE_ROOT%
-if exist %CORE_ROOT% rd /s /q %CORE_ROOT%
-md %CORE_ROOT%
-xcopy /s %__BinDir% %CORE_ROOT%
-call :runtests 
-if ERRORLEVEL 1 (
-    echo Test Run failed. Refer to the following"
-    echo Msbuild log: %__TestRunBuildLog%
-    echo Html report: %__TestRunHtmlLog%
+if not exist %CORE_ROOT%\coreclr.dll (
+    echo %__MsgPrefix%Error: Ensure you have done a successful build of the Product and %CORE_ROOT% contains runtime binaries.
     exit /b 1
 )
 
+if defined __Exclude (if not exist %__Exclude% echo %__MsgPrefix%Error: Exclusion .targets file not found && exit /b 1)
+if defined __TestEnv (if not exist %__TestEnv% echo %__MsgPrefix%Error: Test Environment script not found && exit /b 1)
+
+REM These log files are created automatically by the test run process. Q: what do they depend on being set?
+set __TestRunHtmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.html
+set __TestRunXmlLog=%__LogsDir%\TestRun_%__BuildOS%__%__BuildArch%__%__BuildType%.xml
+
+echo %__MsgPrefix%CORE_ROOT that will be used is: %CORE_ROOT%
+echo %__MsgPrefix%Starting the test run ...
+
+if "%__SkipWrapperGeneration%"=="true" goto SkipWrapperGeneration
+
+set __BuildLogRootName=Tests_XunitWrapper
+call :msbuild "%__ProjectFilesDir%\runtest.proj" /p:NoRun=true
+if errorlevel 1 exit /b 1
+
+:SkipWrapperGeneration
+
+if not "%noCore_RootSet%"=="true" goto SkipCoreRootSetup
+
+set "CORE_ROOT=%XunitTestBinBase%\Tests\Core_Root"
+echo %__MsgPrefix%Using Default CORE_ROOT as %CORE_ROOT%
+echo %__MsgPrefix%Copying Built binaries from %__BinDir% to %CORE_ROOT%
+if exist "%CORE_ROOT%" rd /s /q "%CORE_ROOT%"
+md "%CORE_ROOT%"
+xcopy /s "%__BinDir%" "%CORE_ROOT%"
+
+:SkipCoreRootSetup
+
+set __BuildLogRootName=TestRunResults
+call :msbuild "%__ProjectFilesDir%\runtest.proj" /p:NoBuild=true /clp:showcommandline
+
+if errorlevel 1 (
+    echo Test Run failed. Refer to the following:
+    echo     Html report: %__TestRunHtmlLog%
+    exit /b 1
+)
+
+REM =========================================================================================
+REM ===
+REM === All tests complete!
+REM ===
+REM =========================================================================================
+
+echo %__MsgPrefix%Test run successful. Refer to the log files for details:
+echo     %__TestRunHtmlLog%
+echo     %__TestRunXmlLog%
 exit /b 0
 
-:runtests
-%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%runtest.proj" /p:NoBuild=true /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:LogFile="%__TestRunBuildLog%";Append %1 %_buildpostfix% /clp:showcommandline
-exit /b %ERRORLEVEL%
+REM =========================================================================================
+REM ===
+REM === Helper routines
+REM ===
+REM =========================================================================================
+
+:msbuild
+@REM Subroutine to invoke msbuild. All arguments are passed to msbuild. The first argument should be the
+@REM .proj file to invoke.
+@REM
+@REM On entry, __BuildLogRootName must be set to a file name prefix for the generated log file.
+@REM All the "standard" environment variables that aren't expected to change per invocation must also be set,
+@REM like __msbuildCommonArgs.
+@REM
+@REM The build log files will be overwritten, not appended to.
+
+echo %__MsgPrefix%Invoking msbuild
+
+set "__BuildLog=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
+set "__BuildWrn=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn"
+set "__BuildErr=%__LogsDir%\%__BuildLogRootName%_%__BuildOS%__%__BuildArch%__%__BuildType%.err"
+
+set __msbuildLogArgs=^
+/fileloggerparameters:Verbosity=normal;LogFile="%__BuildLog%";Append ^
+/fileloggerparameters1:WarningsOnly;LogFile="%__BuildWrn%" ^
+/fileloggerparameters2:ErrorsOnly;LogFile="%__BuildErr%" ^
+/consoleloggerparameters:Summary ^
+/verbosity:minimal
 
-:PerformXunitWrapperBuild
+set __msbuildArgs=%* %__msbuildCommonArgs% %__msbuildLogArgs%
 
-%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%runtest.proj" /p:NoRun=true /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:LogFile="%__XunitWrapperBuildLog%";Append %1  %_buildappend%%_buildpostfix%
-exit /b %ERRORLEVEL%
+@REM The next line will overwrite the existing log file, if any.
+echo Invoking: %_msbuildexe% %__msbuildArgs% > "%__BuildLog%"
+
+%_msbuildexe% %__msbuildArgs%
+if errorlevel 1 (
+    echo %__MsgPrefix%Error: msbuild failed. Refer to the log files for details:
+    echo     %__BuildLog%
+    echo     %__BuildWrn%
+    echo     %__BuildErr%
+    exit /b 1
+)
+
+exit /b 0
 
 :Usage
 echo.
 echo Usage:
-echo %0 BuildArch BuildType [SkipWrapperGeneration] [Exclude EXCLUSION_TARGETS] [TestEnv TEST_ENV_SCRIPT] [vsversion] CORE_ROOT   where:
+echo   %0 BuildArch BuildType [SkipWrapperGeneration] [Exclude EXCLUSION_TARGETS] [TestEnv TEST_ENV_SCRIPT] [VSVersion] CORE_ROOT
+echo where:
 echo.
-echo BuildArch is x64, x86
-echo BuildType can be: Debug, Release, Checked
+echo./? -? /h -h /help -help: view this message.
+echo BuildArch- Optional parameter - x64 or x86 ^(default: x64^).
+echo BuildType- Optional parameter - Debug, Release, or Checked ^(default: Debug^).
 echo SkipWrapperGeneration- Optional parameter - this will run the same set of tests as the last time it was run
 echo Exclude0- Optional parameter - specify location of default exclusion file (defaults to issues.targets if not specified)
 echo                                Set to "" to disable default exclusion file.
 echo Exclude-  Optional parameter - this will exclude individual tests from running, specified by ExcludeList ItemGroup in an .targets file.
 echo TestEnv- Optional parameter - this will run a custom script to set custom test environment settings.
-echo VSVersion- optional argument to use VS2013 or VS2015  (default VS2015)
+echo VSVersion- Optional parameter - VS2013 or VS2015 ^(default: VS2015^)
 echo CORE_ROOT The path to the runtime  
 exit /b 1
 
+:NoVS
+echo Visual Studio 2013+ ^(Community is free^) is a prerequisite to build this repository.
+echo See: https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md#prerequisites
+exit /b 1