From 827b5f15e2fd9d642491ebb21bce8013d9937083 Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Wed, 11 Jul 2018 11:32:41 -0700 Subject: [PATCH] Enable Windows ARM64 corefx jobs Disable various tests that currently fail, tagged with issues describing the failures. --- netci.groovy | 102 ++++++++++++++------------------- tests/arm64/corefx_test_exclusions.txt | 12 +++- tests/scripts/run-corefx-tests.bat | 29 ++++++---- tests/scripts/run-corefx-tests.py | 29 ++++++---- 4 files changed, 89 insertions(+), 83 deletions(-) diff --git a/netci.groovy b/netci.groovy index db99a28..34fa6d9 100755 --- a/netci.groovy +++ b/netci.groovy @@ -1567,10 +1567,9 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} via ILLink", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+${scenario}.*") break } - - else if (scenario == 'corefx_innerloop') { + else if (scenario == 'corefx_innerloop') { if (configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") } else { Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests", "(?i).*test\\W+${os}\\W+${architecture}\\W+${configuration}\\W+CoreFX Tests.*") @@ -1641,7 +1640,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, case 'corefx_innerloop': if (configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") } break @@ -1763,7 +1762,7 @@ def static addTriggers(def job, def branch, def isPR, def architecture, def os, break case 'corefx_innerloop': if (configuration == 'Checked') { - Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") + Utilities.addGithubPRTriggerForBranch(job, branch, "${os} ${architecture} ${configuration} CoreFX Tests") } break @@ -2237,22 +2236,21 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR // Archive and process (only) the test results Utilities.addArchival(newJob, "bin/Logs/**/testResults.xml") Utilities.addXUnitDotNETResults(newJob, "bin/Logs/**/testResults.xml") - } else { - def workspaceRelativeFxRoot = "_/fx" - def absoluteFxRoot = "%WORKSPACE%\\_\\fx" - def fxBranch = getFxBranch(branch) + def workspaceRelativeFxRoot = "_/fx" + def absoluteFxRoot = "%WORKSPACE%\\_\\fx" + def fxBranch = getFxBranch(branch) - buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${arch} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath}" + buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${arch} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath}" - // Archive and process (only) the test results - Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml") - Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml") + // Archive and process (only) the test results + Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml") + Utilities.addXUnitDotNETResults(newJob, "${workspaceRelativeFxRoot}/bin/**/testResults.xml") - //Archive additional build stuff to diagnose why my attempt at fault injection isn't causing CI to fail - Utilities.addArchival(newJob, "SetStressModes.bat", "", true, false) - Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/testhost/**", "", true, false) + //Archive additional build stuff to diagnose why my attempt at fault injection isn't causing CI to fail + Utilities.addArchival(newJob, "SetStressModes.bat", "", true, false) + Utilities.addArchival(newJob, "${workspaceRelativeFxRoot}/bin/testhost/**", "", true, false) } } else if (isGcReliabilityFramework(scenario)) { @@ -2298,32 +2296,26 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR } break case 'arm': + case 'arm64': assert isArmWindowsScenario(scenario) - def buildArchitecture = 'arm' def buildOpts = '' + if (architecture == 'arm64') { + buildOpts += " toolset_dir C:\\ats2" + } + if (doCoreFxTesting) { - // We shouldn't need to build the tests. However, run-corefx-tests.py currently depends on having the restored corefx - // package available, to determine the correct corefx version git commit hash, and we need to build the tests before - // running "tests\\runtest.cmd GenerateLayoutOnly". So build the pri-0 tests to make this happen. - // - // buildOpts += ' skiptests'; - buildOpts += " -priority=0" + buildOpts += ' skiptests' } else { buildOpts += " -priority=${priority}" } // This is now a build only job. Do not run tests. Use the flow job. - buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${buildArchitecture} ${buildOpts}" + buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} ${buildOpts}" if (doCoreFxTesting) { assert isBuildOnly - assert architecture == 'arm' - - // Generate the test layout because it restores the corefx package which allows run-corefx-tests.py - // to determine the correct matching corefx version git commit hash. - buildCommands += "tests\\runtest.cmd ${lowerConfiguration} ${architecture} GenerateLayoutOnly" // Set the stress mode variables; this is incorporated into the generated CoreFx RunTests.cmd files. def envScriptPath = '' @@ -2339,10 +2331,15 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR def absoluteFxRoot = "%WORKSPACE%\\_\\fx" def fxBranch = getFxBranch(branch) - buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath} -no_run_tests" + def toolsetDirOpt = '' + if (architecture == 'arm64') { + toolsetDirOpt = "-toolset_dir C:\\ats2" + } + + buildCommands += "python -u %WORKSPACE%\\tests\\scripts\\run-corefx-tests.py -arch ${architecture} -ci_arch ${architecture} -build_type ${configuration} -fx_root ${absoluteFxRoot} -fx_branch ${fxBranch} -env_script ${envScriptPath} -no_run_tests ${toolsetDirOpt}" // Zip up the CoreFx runtime and tests. We don't need the CoreCLR binaries; they have been copied to the CoreFX tree. - buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm', '${workspaceRelativeFxRootWin}\\fxruntime.zip')\""; + buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}', '${workspaceRelativeFxRootWin}\\fxruntime.zip')\""; buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('${workspaceRelativeFxRootWin}\\bin\\tests', '${workspaceRelativeFxRootWin}\\fxtests.zip')\""; Utilities.addArchival(newJob, "${workspaceRelativeFxRootLinux}/fxruntime.zip") @@ -2350,25 +2347,12 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR } else { // Zip up the tests directory so that we don't use so much space/time copying // 10s of thousands of files around. - buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${buildArchitecture}.${configuration}', '.\\bin\\tests\\tests.zip')\""; + buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}', '.\\bin\\tests\\tests.zip')\""; // Add archival. Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**") } break - case 'arm64': - assert isArmWindowsScenario(scenario) - - // This is now a build only job. Do not run tests. Use the flow job. - buildCommands += "set __TestIntermediateDir=int&&build.cmd ${lowerConfiguration} ${architecture} toolset_dir C:\\ats2 -priority=${priority}" - - // Zip up the tests directory so that we don't use so much space/time copying - // 10s of thousands of files around. - buildCommands += "powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}', '.\\bin\\tests\\tests.zip')\""; - - // Add archival. - Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip", "bin/Product/**/.nuget/**") - break default: println("Unknown architecture: ${architecture}"); assert false @@ -2425,7 +2409,7 @@ def static calculateBuildCommands(def newJob, def scenario, def branch, def isPR Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml') } else { - if(scenario == 'corefx_innerloop') { + if (scenario == 'corefx_innerloop') { assert os == 'Ubuntu' || 'OSX10.12' assert architecture == 'x64' @@ -2651,7 +2635,8 @@ def static shouldGenerateJob(def scenario, def isPR, def architecture, def confi if (isBuildOnly) { switch (architecture) { case 'arm': - // We use build only jobs for Windows arm cross-compilation corefx testing, so we need to generate builds for that. + case 'arm64': + // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that. if (!isCoreFxScenario(scenario)) { return false } @@ -2693,7 +2678,7 @@ def static shouldGenerateJob(def scenario, def isPR, def architecture, def confi break case 'arm': - // We use build only jobs for Windows arm cross-compilation corefx testing, so we need to generate builds for that. + // We use build only jobs for Windows arm/arm64 cross-compilation corefx testing, so we need to generate builds for that. // No "regular" Windows arm corefx jobs, e.g. // For Ubuntu arm corefx testing, we use regular jobs (not "build only" since only Windows has "build only", and // the Ubuntu arm "regular" jobs don't run tests anyway). @@ -2711,7 +2696,9 @@ def static shouldGenerateJob(def scenario, def isPR, def architecture, def confi case 'arm64': if (os == 'Windows_NT') { - return false + if (! (isBuildOnly && isCoreFxScenario(scenario)) ) { + return false + } } else { if (!isCoreFxScenario(scenario)) { @@ -3001,20 +2988,20 @@ def static CreateWindowsArmTestJob(def dslFactory, def project, def architecture if (isCoreFxScenario(scenario)) { - // Only arm supported for corefx testing now. - assert architecture == 'arm' + // Only arm/arm64 supported for corefx testing now. + assert architecture == 'arm' || architecture == 'arm64' // Unzip CoreFx runtime - batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxruntime.zip', '_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm')\"") + batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxruntime.zip', '_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}')\"") // Unzip CoreFx tests. batchFile("powershell -NoProfile -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('_\\fx\\fxtests.zip', '_\\fx\\bin\\tests')\"") // Add the script to run the corefx tests - def corefx_runtime_path = "%WORKSPACE%\\_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-arm" + def corefx_runtime_path = "%WORKSPACE%\\_\\fx\\bin\\testhost\\netcoreapp-Windows_NT-Release-${architecture}" def corefx_tests_dir = "%WORKSPACE%\\_\\fx\\bin\\tests" - def corefx_exclusion_file = "%WORKSPACE%\\tests\\arm\\corefx_test_exclusions.txt" - batchFile("call %WORKSPACE%\\tests\\scripts\\run-corefx-tests.bat ${corefx_runtime_path} ${corefx_tests_dir} ${corefx_exclusion_file}") + def corefx_exclusion_file = "%WORKSPACE%\\tests\\${architecture}\\corefx_test_exclusions.txt" + batchFile("call %WORKSPACE%\\tests\\scripts\\run-corefx-tests.bat ${corefx_runtime_path} ${corefx_tests_dir} ${corefx_exclusion_file} ${architecture}") } else { // !isCoreFxScenario(scenario) @@ -3633,11 +3620,6 @@ def static shouldGenerateFlowJob(def scenario, def isPR, def architecture, def c if (configuration != 'Checked') { return false } - - // On Windows, CoreFx tests currently not implemented for ARM64. - if (isCoreFxScenario(scenario) && (os == 'Windows_NT') && (architecture == 'arm64')) { - return false - } } else if (isR2RBaselineScenario(scenario)) { if (configuration != 'Checked' && configuration != 'Release') { diff --git a/tests/arm64/corefx_test_exclusions.txt b/tests/arm64/corefx_test_exclusions.txt index 6b00a58..660069e 100644 --- a/tests/arm64/corefx_test_exclusions.txt +++ b/tests/arm64/corefx_test_exclusions.txt @@ -1,3 +1,13 @@ Invariant.Tests -System.Diagnostics.Process.Tests +System.ComponentModel.Composition.Tests # https://github.com/dotnet/coreclr/issues/18913 +System.Diagnostics.Process.Tests # https://github.com/dotnet/coreclr/issues/16001 +System.Drawing.Common.Tests # https://github.com/dotnet/coreclr/issues/18886 +System.Linq.Expressions.Tests # JitStress=1 JitStress=2 https://github.com/dotnet/coreclr/issues/18886 +System.Management.Tests # https://github.com/dotnet/coreclr/issues/18886 +System.Net.HttpListener.Tests # https://github.com/dotnet/coreclr/issues/17584 +System.Numerics.Vectors.Tests # https://github.com/dotnet/coreclr/issues/18886 +System.Runtime.InteropServices.RuntimeInformation.Tests # VM assert -- https://github.com/dotnet/coreclr/issues/18886 +System.Runtime.Serialization.Formatters.Tests # long running? https://github.com/dotnet/coreclr/issues/18886 +System.Runtime.Tests # https://github.com/dotnet/coreclr/issues/18914 +System.Text.RegularExpressions.Tests # https://github.com/dotnet/coreclr/issues/18912 -- timeout -- JitMinOpts only System.ValueTuple.Tests diff --git a/tests/scripts/run-corefx-tests.bat b/tests/scripts/run-corefx-tests.bat index 32103f2..b77644f 100644 --- a/tests/scripts/run-corefx-tests.bat +++ b/tests/scripts/run-corefx-tests.bat @@ -5,17 +5,19 @@ goto start :usage echo Usage: run-corefx-tests.bat ^ ^ ^ echo. -echo Runs the corefx tests on a Windows ARM device, by searching for all relevant corefx +echo Runs the corefx tests on a Windows ARM/ARM64 device, by searching for all relevant corefx echo RunTests.cmd files in the ^ tree, and running each one in turn. This -echo script is typically run on a Windows ARM machine after the run-corefx-test.py script +echo script is typically run on a Windows ARM/ARM64 machine after the run-corefx-test.py script echo is run on a Windows x64 machine with the `-no_run_tests` argument, to build the echo corefx tree, including tests, and then copying the built runtime layout and tests -echo to the ARM machine. +echo to the ARM/ARM64 machine. echo. echo Arguments: -echo ^ -- Path to corefx-built runtime "layout", e.g. _\fx\bin\testhost\netcoreapp-Windows_NT-Release-arm -echo ^ -- Path to corefx test tree, e.g., _\fx\bin\tests +echo ^ -- Path to corefx-built runtime "layout", e.g. _\fx\bin\testhost\netcoreapp-Windows_NT-Release-arm +echo ^ -- Path to corefx test tree, e.g., _\fx\bin\tests echo ^ -- Path to test exclusion file, e.g., C:\coreclr\tests\arm\corefx_test_exclusions.txt +echo ^ -- Architecture to run, either ARM or ARM64. (We can't depend on PROCESSOR_ARCHITECTURE because +echo the batch script might be invoked with an ARM64 CMD but we need to run ARM.) echo. echo The ^ is a file with a list of assemblies for which the echo tests should not be run. This allows excluding failing tests by excluding the @@ -26,23 +28,22 @@ echo. echo System.Console.Tests echo System.Data.SqlClient.Tests echo System.Diagnostics.Process.Tests -echo. -echo This script only works for Windows ARM, but perhaps should be extended to work -echo for Windows ARM64 as well. goto :eof :start -if "%3"=="" goto usage -if not "%4"=="" goto usage +if "%4"=="" goto usage +if not "%5"=="" goto usage set _runtime_path=%1 set _tests_dir=%2 set _exclusion_file=%3 +set _architecture=%4 echo Running CoreFX tests echo Using runtime: %_runtime_path% echo Using tests: %_tests_dir% echo Using test exclusion file: %_exclusion_file% +echo Using architecture: %_architecture% set _pass=0 set _fail=0 @@ -50,7 +51,7 @@ set _skipped=0 set _total=0 pushd %_tests_dir% -for /F %%i in ('dir /s /b /A:D netcoreapp-Windows_NT-Release-arm') do ( +for /F %%i in ('dir /s /b /A:D netcoreapp-Windows_NT-Release-%_architecture%') do ( if exist %%i\RunTests.cmd call :one %%i ) popd @@ -69,7 +70,11 @@ REM From this, we want System.Management.Tests to compare against the exclusion REM of test names to skip. set _t1=%1 -set _t2=%_t1:\netcoreapp-Windows_NT-Release-arm=% +if /i %_architecture%==arm ( + set _t2=%_t1:\netcoreapp-Windows_NT-Release-arm=% +) else ( + set _t2=%_t1:\netcoreapp-Windows_NT-Release-arm64=% +) for /F %%j in ("%_t2%") do set _t3=%%~nxj findstr /i %_t3% %_exclusion_file% >nul if %errorlevel% EQU 0 ( diff --git a/tests/scripts/run-corefx-tests.py b/tests/scripts/run-corefx-tests.py index 4acd5d2..a45f5d6 100644 --- a/tests/scripts/run-corefx-tests.py +++ b/tests/scripts/run-corefx-tests.py @@ -70,6 +70,7 @@ parser.add_argument('-fx_branch', dest='fx_branch', default='master') parser.add_argument('-fx_commit', dest='fx_commit', default=None) parser.add_argument('-env_script', dest='env_script', default=None) parser.add_argument('-no_run_tests', dest='no_run_tests', action="store_true", default=False) +parser.add_argument('-toolset_dir', dest='toolset_dir', default='c:\\ats2') ########################################################################## @@ -81,8 +82,8 @@ def validate_args(args): Args: args (argparser.ArgumentParser): Args parsed by the argument parser. Returns: - (arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests) - (str, str, str, str, str, str, str, str) + (arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests, toolset_dir) + (str, str, str, str, str, str, str, str, str) Notes: If the arguments are valid then return them all in a tuple. If not, raise an exception stating x argument is incorrect. @@ -97,6 +98,7 @@ def validate_args(args): fx_commit = args.fx_commit env_script = args.env_script no_run_tests = args.no_run_tests + toolset_dir = args.toolset_dir def validate_arg(arg, check): """ Validate an individual arg @@ -142,7 +144,7 @@ def validate_args(args): validate_arg(env_script, lambda item: os.path.isfile(env_script)) env_script = os.path.abspath(env_script) - args = (arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests) + args = (arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests, toolset_dir) log('Configuration:') log(' arch: %s' % arch) @@ -154,6 +156,7 @@ def validate_args(args): log(' fx_commit: %s' % fx_commit) log(' env_script: %s' % env_script) log(' no_run_tests: %s' % no_run_tests) + log(' toolset_dir: %s' % toolset_dir) return args @@ -215,7 +218,7 @@ def main(args): global Unix_name_map global testing - arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests = validate_args( + arch, ci_arch, build_type, clr_root, fx_root, fx_branch, fx_commit, env_script, no_run_tests, toolset_dir = validate_args( args) clr_os = 'Windows_NT' if Is_windows else Unix_name_map[os.uname()[0]] @@ -276,11 +279,8 @@ def main(args): os.makedirs(fx_home) os.putenv('HOME', fx_home) log('HOME=' + fx_home) - - # Determine the RID to specify the to corefix build scripts. This seems to - # be way harder than it ought to be. - # Gather up some arguments to pass to both build and build-tests. + # Gather up some arguments to pass to build-managed, build-native, and build-tests scripts. config_args = '-Release -os:%s -buildArch:%s' % (clr_os, arch) @@ -300,17 +300,23 @@ def main(args): # Cross build corefx for arm32 on x86. build_native_args = '' + if not Is_windows and arch == 'arm' : # We need to force clang5.0; we are building in a docker container that doesn't have # clang3.9, which is currently the default used by build-native.sh. We need to pass # "-cross", but we also pass "-portable", which build-native.sh normally passes # (there doesn't appear to be a way to pass these individually). - build_native_args = '-AdditionalArgs:"-portable -cross" -Clang:clang5.0' + build_native_args += ' -AdditionalArgs:"-portable -cross" -Clang:clang5.0' if not Is_windows and arch == 'arm64' : # We need to pass "-cross", but we also pass "-portable", which build-native.sh normally # passes (there doesn't appear to be a way to pass these individually). - build_native_args = '-AdditionalArgs:"-portable -cross"' + build_native_args += ' -AdditionalArgs:"-portable -cross"' + + if Is_windows and arch == 'arm64' : + # We need to pass toolsetDir to specify the arm64 private toolset. + # This is temporary, until private toolset is no longer used. So hard-code the CI toolset dir. + build_native_args += ' -ToolSetDir:"toolsetDir=%s"' % toolset_dir command = ' '.join(('build-native.cmd' if Is_windows else './build-native.sh', config_args, @@ -318,12 +324,14 @@ def main(args): log(command) returncode = 0 if testing else os.system(command) if returncode != 0: + log('Error: exit code %s' % returncode) sys.exit(1) command = ' '.join(('build-managed.cmd' if Is_windows else './build-managed.sh', config_args)) log(command) returncode = 0 if testing else os.system(command) if returncode != 0: + log('Error: exit code %s' % returncode) sys.exit(1) # Override the built corefx runtime (which it picked up by copying from packages determined @@ -381,6 +389,7 @@ def main(args): log(command) returncode = 0 if testing else os.system(command) if returncode != 0: + log('Error: exit code %s' % returncode) sys.exit(1) sys.exit(0) -- 2.7.4