Fix verification of 3-byte UTF-8 sequence followed by non-ASCII byte (#24235)
[platform/upstream/coreclr.git] / build-test.sh
1 #!/usr/bin/env bash
2
3 __PortableBuild=1
4
5 initTargetDistroRid()
6 {
7     source init-distro-rid.sh
8
9     # Only pass ROOTFS_DIR if cross is specified.
10     if (( ${__CrossBuild} == 1 )); then
11         passedRootfsDir=${ROOTFS_DIR}
12     fi
13
14     initDistroRidGlobal ${__BuildOS} ${__BuildArch} ${__PortableBuild} ${passedRootfsDir}
15 }
16
17 isMSBuildOnNETCoreSupported()
18 {
19     __isMSBuildOnNETCoreSupported=$__msbuildonunsupportedplatform
20
21     if [ $__isMSBuildOnNETCoreSupported == 1 ]; then
22         return
23     fi
24
25     if [ "$__HostArch" == "x64" ]; then
26         if [ "$__HostOS" == "Linux" ]; then
27             __isMSBuildOnNETCoreSupported=1
28             UNSUPPORTED_RIDS=("debian.9-x64" "ubuntu.17.04-x64")
29             for UNSUPPORTED_RID in "${UNSUPPORTED_RIDS[@]}"
30             do
31                 if [ "${__DistroRid}" == "$UNSUPPORTED_RID" ]; then
32                     __isMSBuildOnNETCoreSupported=0
33                     break
34                 fi
35             done
36         elif [ "$__HostOS" == "OSX" ]; then
37             __isMSBuildOnNETCoreSupported=1
38         fi
39     fi
40 }
41
42 build_test_wrappers()
43 {
44     if [ $__BuildTestWrappers -ne -0 ]; then
45         echo "${__MsgPrefix}Creating test wrappers..."
46
47         export __Exclude="${__ProjectDir}/tests/issues.targets"
48         export __BuildLogRootName="Tests_XunitWrapper"
49
50         buildVerbosity="Summary"
51
52         if [ $__VerboseBuild == 1 ]; then
53             buildVerbosity="Diag"
54         fi
55
56         # Set up directories and file names
57         __BuildLogRootName=$subDirectoryName
58         __BuildLog="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.log"
59         __BuildWrn="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.wrn"
60         __BuildErr="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.err"
61         __MsbuildLog="/fileloggerparameters:\"Verbosity=normal;LogFile=${__BuildLog}\""
62         __MsbuildWrn="/fileloggerparameters1:\"WarningsOnly;LogFile=${__BuildWrn}\""
63         __MsbuildErr="/fileloggerparameters2:\"ErrorsOnly;LogFile=${__BuildErr}\""
64         __Logging="$__MsbuildLog $__MsbuildWrn $__MsbuildErr /consoleloggerparameters:$buildVerbosity"
65
66         nextCommand="\"${__DotNetCli}\" msbuild \"${__ProjectDir}/tests/runtest.proj\" /p:RestoreAdditionalProjectSources=https://dotnet.myget.org/F/dotnet-core/ /p:BuildWrappers=true /p:TargetsWindows=false $__Logging /p:__BuildOS=$__BuildOS /p:__BuildType=$__BuildType /p:__BuildArch=$__BuildArch"
67         eval $nextCommand
68
69         if [ $? -ne 0 ]; then
70             echo "${__MsgPrefix}Error: build failed. Refer to the build log files for details (above)"
71             exit 1
72         else
73             echo "XUnit Wrappers have been built."
74             echo { "\"build_os\"": "\"${__BuildOS}\"", "\"build_arch\"": "\"${__BuildArch}\"", "\"build_type\"": "\"${__BuildType}\"" } > "${__TestWorkingDir}/build_info.json"
75
76         fi
77     fi
78 }
79
80 generate_layout()
81 {
82     echo "${__MsgPrefix}Creating test overlay..."
83
84     __TestDir=$__ProjectDir/tests
85     __ProjectFilesDir=$__TestDir
86     __TestBinDir=$__TestWorkingDir
87
88     if [ $__RebuildTests -ne 0 ]; then
89         if [ -d "${__TestBinDir}" ]; then
90             echo "Removing tests build dir: ${__TestBinDir}"
91             rm -rf $__TestBinDir
92         fi
93     fi
94
95     __CMakeBinDir="${__TestBinDir}"
96
97     if [ -z "$__TestIntermediateDir" ]; then
98         __TestIntermediateDir="tests/obj/${__BuildOS}.${__BuildArch}.${__BuildType}"
99     fi
100
101     echo "__BuildOS: ${__BuildOS}"
102     echo "__BuildArch: ${__BuildArch}"
103     echo "__BuildType: ${__BuildType}"
104     echo "__TestIntermediateDir: ${__TestIntermediateDir}"
105
106     if [ ! -f "$__TestBinDir" ]; then
107         echo "Creating TestBinDir: ${__TestBinDir}"
108         mkdir -p $__TestBinDir
109     fi
110     if [ ! -f "$__LogsDir" ]; then
111         echo "Creating LogsDir: ${__LogsDir}"
112         mkdir -p $__LogsDir
113     fi
114     if [ ! -f "$__MsbuildDebugLogsDir" ]; then
115         echo "Creating MsbuildDebugLogsDir: ${__MsbuildDebugLogsDir}"
116         mkdir -p $__MsbuildDebugLogsDir
117     fi
118
119     # Set up the directory for MSBuild debug logs.
120     export MSBUILDDEBUGPATH="${__MsbuildDebugLogsDir}"
121
122     __BuildProperties="-p:OSGroup=${__BuildOS} -p:BuildOS=${__BuildOS} -p:BuildArch=${__BuildArch} -p:BuildType=${__BuildType}"
123
124     # =========================================================================================
125     # ===
126     # === Restore product binaries from packages
127     # ===
128     # =========================================================================================
129
130     build_MSBuild_projects "Restore_Packages" "${__ProjectDir}/tests/build.proj" "Restore product binaries (build tests)" "/t:BatchRestorePackages"
131
132     if [ -n "$__UpdateInvalidPackagesArg" ]; then
133         __up="/t:UpdateInvalidPackageVersions"
134     fi
135
136     echo "${__MsgPrefix}Creating test overlay..."
137
138     if [ -z "$xUnitTestBinBase" ]; then
139         xUnitTestBinBase=$__TestWorkingDir
140     fi
141
142     export CORE_ROOT=$xUnitTestBinBase/Tests/Core_Root
143
144     if [ -d "${CORE_ROOT}" ]; then
145         rm -rf $CORE_ROOT
146     fi
147
148     mkdir -p $CORE_ROOT
149
150     build_MSBuild_projects "Tests_Overlay_Managed" "${__ProjectDir}/tests/runtest.proj" "Creating test overlay" "/t:CreateTestOverlay"
151
152     chmod +x $__BinDir/corerun
153     chmod +x $__CrossgenExe
154
155     # Make sure to copy over the pulled down packages
156     cp -r $__BinDir/* $CORE_ROOT/ > /dev/null
157
158     if [ "$__BuildOS" != "OSX" ]; then
159         nextCommand="\"$__TestDir/setup-stress-dependencies.sh\" --outputDir=$CORE_ROOT"
160         echo "Resolve runtime dependences via $nextCommand"
161         eval $nextCommand
162     fi
163
164     # Precompile framework assemblies with crossgen if required
165     if [ $__DoCrossgen -ne 0 ]; then
166         precompile_coreroot_fx
167     fi
168 }
169
170 precompile_coreroot_fx()
171 {
172     echo "${__MsgPrefix}Running crossgen on framework assemblies in CORE_ROOT: '${CORE_ROOT}'"
173
174     # Read the exclusion file for this platform
175     skipCrossGenFiles=($(read_array "$(dirname "$0")/tests/skipCrossGenFiles.${__BuildArch}.txt"))
176
177     local overlayDir=$CORE_ROOT
178
179     filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -not -iname \*-ms-win-\* -not -iname xunit.\* -type f)
180     for fileToPrecompile in ${filesToPrecompile}
181     do
182         local filename=${fileToPrecompile}
183         if is_skip_crossgen_test "$(basename $filename)"; then
184                 continue
185         fi
186         echo Precompiling $filename
187         $__CrossgenExe /Platform_Assemblies_Paths $overlayDir $filename 1> $filename.stdout 2>$filename.stderr
188         local exitCode=$?
189         if [[ $exitCode != 0 ]]; then
190             if grep -q -e '0x80131018' $filename.stderr; then
191                 printf "\n\t$filename is not a managed assembly.\n\n"
192             else
193                 echo Unable to precompile $filename.
194                 cat $filename.stdout
195                 cat $filename.stderr
196                 exit $exitCode
197             fi
198         else
199             rm $filename.{stdout,stderr}
200         fi
201     done
202 }
203
204 declare -a skipCrossGenFiles
205
206 function is_skip_crossgen_test {
207     for skip in "${skipCrossGenFiles[@]}"; do
208         if [ "$1" == "$skip" ]; then
209             return 0
210         fi
211     done
212     return 1
213 }
214
215 # Get an array of items by reading the specified file line by line.
216 function read_array {
217     local theArray=()
218
219     if [ ! -f "$1" ]; then
220         return
221     fi
222
223     # bash in Mac OS X doesn't support 'readarray', so using alternate way instead.
224     # readarray -t theArray < "$1"
225     # Any line that starts with '#' is ignored.
226     while IFS='' read -r line || [ -n "$line" ]; do
227         if [[ $line != "#"* ]]; then
228             theArray[${#theArray[@]}]=$line
229         fi
230     done < "$1"
231     echo ${theArray[@]}
232 }
233
234 generate_testhost()
235 {
236     echo "${__MsgPrefix}Generating test host..."
237
238     export TEST_HOST=$xUnitTestBinBase/testhost
239
240     if [ -d "${TEST_HOST}" ]; then
241         rm -rf $TEST_HOST
242     fi
243
244     mkdir -p $TEST_HOST
245
246     build_MSBuild_projects "Tests_Generate_TestHost" "${__ProjectDir}/tests/runtest.proj" "Creating test host" "/t:CreateTestHost"
247 }
248
249
250 build_Tests()
251 {
252     echo "${__MsgPrefix}Building Tests..."
253
254     __TestDir=$__ProjectDir/tests
255     __ProjectFilesDir=$__TestDir
256     __TestBinDir=$__TestWorkingDir
257
258     if [ -f  "${__TestWorkingDir}/build_info.json" ]; then
259         rm  "${__TestWorkingDir}/build_info.json"
260     fi
261
262     if [ $__RebuildTests -ne 0 ]; then
263         if [ -d "${__TestBinDir}" ]; then
264             echo "Removing tests build dir: ${__TestBinDir}"
265             rm -rf $__TestBinDir
266         fi
267     fi
268
269     export __CMakeBinDir="${__TestBinDir}"
270     if [ ! -d "${__TestIntermediatesDir}" ]; then
271         mkdir -p ${__TestIntermediatesDir}
272     fi
273
274     __NativeTestIntermediatesDir="${__TestIntermediatesDir}/Native"
275     if [  ! -d "${__NativeTestIntermediatesDir}" ]; then
276         mkdir -p ${__NativeTestIntermediatesDir}
277     fi
278
279     __ManagedTestIntermediatesDir="${__TestIntermediatesDir}/Managed"
280     if [ ! -d "${__ManagedTestIntermediatesDir}" ]; then
281         mkdir -p ${__ManagedTestIntermediatesDir}
282     fi
283
284     echo "__BuildOS: ${__BuildOS}"
285     echo "__BuildArch: ${__BuildArch}"
286     echo "__BuildType: ${__BuildType}"
287     echo "__TestIntermediatesDir: ${__TestIntermediatesDir}"
288     echo "__NativeTestIntermediatesDir: ${__NativeTestIntermediatesDir}"
289     echo "__ManagedTestIntermediatesDir: ${__ManagedTestIntermediatesDir}"
290
291     if [ ! -f "$__TestBinDir" ]; then
292         echo "Creating TestBinDir: ${__TestBinDir}"
293         mkdir -p $__TestBinDir
294     fi
295     if [ ! -f "$__LogsDir" ]; then
296         echo "Creating LogsDir: ${__LogsDir}"
297         mkdir -p $__LogsDir
298     fi
299     if [ ! -f "$__MsbuildDebugLogsDir" ]; then
300         echo "Creating MsbuildDebugLogsDir: ${__MsbuildDebugLogsDir}"
301         mkdir -p $__MsbuildDebugLogsDir
302     fi
303
304     # Set up the directory for MSBuild debug logs.
305     export MSBUILDDEBUGPATH="${__MsbuildDebugLogsDir}"
306
307     __BuildProperties="-p:OSGroup=${__BuildOS} -p:BuildOS=${__BuildOS} -p:BuildArch=${__BuildArch} -p:BuildType=${__BuildType}"
308
309     # =========================================================================================
310     # ===
311     # === Restore product binaries from packages
312     # ===
313     # =========================================================================================
314
315     if [ ${__SkipRestorePackages} != 1 ]; then
316         build_MSBuild_projects "Restore_Product" "${__ProjectDir}/tests/build.proj" "Restore product binaries (build tests)" "/t:BatchRestorePackages"
317     fi
318
319     if [ $__SkipNative != 1 ]; then
320         build_native_projects "$__BuildArch" "${__NativeTestIntermediatesDir}"
321
322         if [ $? -ne 0 ]; then
323             echo "${__MsgPrefix}Error: build failed. Refer to the build log files for details (above)"
324             exit 1
325         fi
326     fi
327
328     if [ $__SkipManaged != 1 ]; then
329         echo "Starting the Managed Tests Build..."
330
331         build_MSBuild_projects "Tests_Managed" "$__ProjectDir/tests/build.proj" "Managed tests build (build tests)" "$__up"
332
333         if [ $? -ne 0 ]; then
334             echo "${__MsgPrefix}Error: build failed. Refer to the build log files for details (above)"
335             exit 1
336         else
337             echo "Checking the Managed Tests Build..."
338
339             build_MSBuild_projects "Check_Test_Build" "${__ProjectDir}/tests/runtest.proj" "Check Test Build" "/t:CheckTestBuild"
340
341             if [ $? -ne 0 ]; then
342                 echo "${__MsgPrefix}Error: Check Test Build failed."
343                 exit 1
344             fi
345         fi
346
347         echo "Managed tests build success!"
348     fi
349
350     build_test_wrappers
351
352     if [ -n "$__UpdateInvalidPackagesArg" ]; then
353         __up="/t:UpdateInvalidPackageVersions"
354     fi
355
356     generate_layout
357 }
358
359 build_MSBuild_projects()
360 {
361     subDirectoryName=$1
362     shift
363     projectName=$1
364     shift
365     stepName="$1"
366     shift
367     extraBuildParameters=("$@")
368
369     # Set up directories and file names
370     __BuildLogRootName=$subDirectoryName
371     __BuildLog="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.log"
372     __BuildWrn="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.wrn"
373     __BuildErr="$__LogsDir/${__BuildLogRootName}.${__BuildOS}.${__BuildArch}.${__BuildType}.err"
374
375     # Use binclashlogger by default if no other logger is specified
376     if [[ "${extraBuildParameters[*]}" == *"/l:"* ]]; then
377         __msbuildEventLogging=
378     else
379         __msbuildEventLogging="/l:BinClashLogger,Tools/Microsoft.DotNet.Build.Tasks.dll\;LogFile=binclash.log"
380     fi
381
382     if [[ "$subDirectoryName" == "Tests_Managed" ]]; then
383         # Execute msbuild managed test build in stages - workaround for excessive data retention in MSBuild ConfigCache
384         # See https://github.com/Microsoft/msbuild/issues/2993
385
386         # __SkipPackageRestore and __SkipTargetingPackBuild used  to control build by tests/src/dirs.proj
387         export __SkipPackageRestore=false
388         export __SkipTargetingPackBuild=false
389         export __NumberOfTestGroups=3
390
391         __AppendToLog=false
392
393         if [ -n "$__priority1" ]; then
394             export __NumberOfTestGroups=10
395         fi
396
397         for (( testGroupToBuild=1 ; testGroupToBuild <= __NumberOfTestGroups; testGroupToBuild = testGroupToBuild + 1 ))
398         do
399             __msbuildLog="\"/flp:Verbosity=normal;LogFile=${__BuildLog};Append=${__AppendToLog}\""
400             __msbuildWrn="\"/flp1:WarningsOnly;LogFile=${__BuildWrn};Append=${__AppendToLog}\""
401             __msbuildErr="\"/flp2:ErrorsOnly;LogFile=${__BuildErr};Append=${__AppendToLog}\""
402
403             export __TestGroupToBuild=$testGroupToBuild
404
405             # Generate build command
406             buildArgs=("/nologo" "/verbosity:minimal" "/clp:Summary")
407             buildArgs+=("/p:RestoreDefaultOptimizationDataPackage=false" "/p:PortableBuild=true")
408             buildArgs+=("/p:UsePartialNGENOptimization=false" "/maxcpucount")
409
410             buildArgs+=("$projectName" "${__msbuildLog}" "${__msbuildWrn}" "${__msbuildErr}")
411             buildArgs+=("$__msbuildEventLogging")
412             buildArgs+=("${extraBuildParameters[@]}")
413             buildArgs+=("${__CommonMSBuildArgs[@]}")
414             buildArgs+=("${__UnprocessedBuildArgs[@]}")
415
416             nextCommand="\"$__ProjectRoot/dotnet.sh\" msbuild ${buildArgs[@]}"
417             echo "Building step '$stepName' testGroupToBuild=$testGroupToBuild via $nextCommand"
418             eval $nextCommand
419
420             # Make sure everything is OK
421             if [ $? -ne 0 ]; then
422                 echo "${__MsgPrefix}Failed to build $stepName. See the build logs:"
423                 echo "    $__BuildLog"
424                 echo "    $__BuildWrn"
425                 echo "    $__BuildErr"
426                 exit 1
427             fi
428             export __SkipPackageRestore=true
429             export __SkipTargetingPackBuild=true
430             __AppendToLog=true
431         done
432     else
433         __msbuildLog="\"/flp:Verbosity=normal;LogFile=${__BuildLog}\""
434         __msbuildWrn="\"/flp1:WarningsOnly;LogFile=${__BuildWrn}\""
435         __msbuildErr="\"/flp2:ErrorsOnly;LogFile=${__BuildErr}\""
436
437         # Generate build command
438         buildArgs=("/nologo" "/verbosity:minimal" "/clp:Summary")
439         buildArgs+=("/p:RestoreDefaultOptimizationDataPackage=false" "/p:PortableBuild=true")
440         buildArgs+=("/p:UsePartialNGENOptimization=false" "/maxcpucount")
441
442         buildArgs+=("$projectName" "${__msbuildLog}" "${__msbuildWrn}" "${__msbuildErr}")
443         buildArgs+=("$__msbuildEventLogging")
444         buildArgs+=("${extraBuildParameters[@]}")
445         buildArgs+=("${__CommonMSBuildArgs[@]}")
446         buildArgs+=("${__UnprocessedBuildArgs[@]}")
447
448         nextCommand="\"$__ProjectRoot/dotnet.sh\" msbuild ${buildArgs[@]}"
449         echo "Building step '$stepName' via $nextCommand"
450         eval $nextCommand
451
452         # Make sure everything is OK
453         if [ $? -ne 0 ]; then
454             echo "${__MsgPrefix}Failed to build $stepName. See the build logs:"
455             echo "    $__BuildLog"
456             echo "    $__BuildWrn"
457             echo "    $__BuildErr"
458             exit 1
459         fi
460     fi
461 }
462
463 build_native_projects()
464 {
465     platformArch="$1"
466     intermediatesForBuild="$2"
467
468     extraCmakeArguments="-DCLR_CMAKE_TARGET_OS=${__BuildOS} -DCLR_CMAKE_HOST_ARCH=${platformArch}"
469     message="native tests assets"
470
471     # All set to commence the build
472     echo "Commencing build of $message for $__BuildOS.$__BuildArch.$__BuildType in $intermediatesForBuild"
473
474     generator=""
475     buildFile="Makefile"
476     buildTool="make"
477     if [ $__UseNinja == 1 ]; then
478         generator="ninja"
479         buildFile="build.ninja"
480         if ! buildTool=$(command -v ninja || command -v ninja-build); then
481            echo "Unable to locate ninja!" 1>&2
482            exit 1
483         fi
484     fi
485
486     if [ $__SkipConfigure == 0 ]; then
487         # if msbuild is not supported, then set __SkipGenerateVersion to 1
488         if [ $__isMSBuildOnNETCoreSupported == 0 ]; then __SkipGenerateVersion=1; fi
489         # Drop version.c file
490         __versionSourceFile="$intermediatesForBuild/version.c"
491         if [ $__SkipGenerateVersion == 0 ]; then
492             pwd
493             $__ProjectRoot/dotnet.sh msbuild /nologo /verbosity:minimal /clp:Summary \
494                                      /p:RestoreDefaultOptimizationDataPackage=false /p:PortableBuild=true \
495                                      /p:UsePartialNGENOptimization=false /maxcpucount \
496                                      $__ProjectDir/build.proj /t:GenerateVersionHeader \
497                                      /p:GenerateVersionHeader=true /p:NativeVersionSourceFile=$__versionSourceFile \
498                                      /l:BinClashLogger,Tools/Microsoft.DotNet.Build.Tasks.dll\;LogFile=binclash.log \
499                                      $__CommonMSBuildArgs $__UnprocessedBuildArgs
500         else
501             # Generate the dummy version.c, but only if it didn't exist to make sure we don't trigger unnecessary rebuild
502             __versionSourceLine="static char sccsid[] __attribute__((used)) = \"@(#)No version information produced\";"
503             if [ -e $__versionSourceFile ]; then
504                 read existingVersionSourceLine < $__versionSourceFile
505             fi
506             if [ "$__versionSourceLine" != "$existingVersionSourceLine" ]; then
507                 echo $__versionSourceLine > $__versionSourceFile
508             fi
509         fi
510
511         pushd "$intermediatesForBuild"
512         # Regenerate the CMake solution
513         # Force cross dir to point to project root cross dir, in case there is a cross build.
514         scriptDir="$__ProjectRoot/src/pal/tools"
515         if [[ $__GccBuild == 0 ]]; then
516             nextCommand="CONFIG_DIR=\"$__ProjectRoot/cross\" \"$scriptDir/gen-buildsys-clang.sh\" \"$__TestDir\" $__ClangMajorVersion $__ClangMinorVersion $platformArch $scriptDir $__BuildType $__CodeCoverage $generator $extraCmakeArguments $__cmakeargs"
517         else
518             nextCommand="CONFIG_DIR=\"$__ProjectRoot/cross\" \"$scriptDir/gen-buildsys-gcc.sh\" \"$__TestDir\" \"$__GccMajorVersion\" \"$__GccMinorVersion\" $platformArch $scriptDir $__BuildType $__CodeCoverage $generator $extraCmakeArguments $__cmakeargs"
519         fi
520         echo "Invoking $nextCommand"
521         eval $nextCommand
522         popd
523     fi
524
525     if [ ! -f "$intermediatesForBuild/$buildFile" ]; then
526         echo "Failed to generate $message build project!"
527         exit 1
528     fi
529
530     # Build
531     if [ $__ConfigureOnly == 1 ]; then
532         echo "Finish configuration & skipping $message build."
533         return
534     fi
535
536     pushd "$intermediatesForBuild"
537
538     echo "Executing $buildTool install -j $__NumProc"
539
540     $buildTool install -j $__NumProc
541     if [ $? != 0 ]; then
542         echo "Failed to build $message."
543         exit 1
544     fi
545
546     popd
547     echo "Native tests build success!"
548 }
549
550 usage()
551 {
552     echo "Usage: $0 [BuildArch] [BuildType] [verbose] [coverage] [cross] [clangx.y] [ninja] [runtests] [bindir]"
553     echo "BuildArch can be: x64, x86, arm, armel, arm64"
554     echo "BuildType can be: debug, checked, release"
555     echo "coverage - optional argument to enable code coverage build (currently supported only for Linux and OSX)."
556     echo "ninja - target ninja instead of GNU make"
557     echo "clangx.y - optional argument to build using clang version x.y - supported version 3.5 - 6.0"
558     echo "gccx.y - optional argument to build using gcc version x.y."
559     echo "cross - optional argument to signify cross compilation,"
560     echo "      - will use ROOTFS_DIR environment variable if set."
561     echo "portableLinux - build for Portable Linux Distribution"
562     echo "portablebuild - Use portable build."
563     echo "verbose - optional argument to enable verbose build output."
564     echo "rebuild - if tests have already been built - rebuild them"
565     echo "skipnative: skip the native tests build"
566     echo "skipmanaged: skip the managed section of the test build"
567     echo "buildtestwrappersonly - only build the test wrappers"
568     echo "generatelayoutonly - only pull down dependencies and build coreroot"
569     echo "generatetesthostonly - only pull down dependencies and build coreroot and the CoreFX testhost"
570     echo "skiprestorepackages - skip package restore"
571     echo "crossgen - Precompiles the framework managed assemblies in coreroot"
572     echo "runtests - run tests after building them"
573     echo "bindir - output directory (defaults to $__ProjectRoot/bin)"
574     echo "msbuildonunsupportedplatform - build managed binaries even if distro is not officially supported."
575     echo "priority1 - include priority=1 tests in the build"
576     exit 1
577 }
578
579
580 # Obtain the location of the bash script to figure out where the root of the repo is.
581 __ProjectRoot="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
582
583 # Use uname to determine what the CPU is.
584 CPUName=$(uname -p)
585
586 # Some Linux platforms report unknown for platform, but the arch for machine.
587 if [ "$CPUName" == "unknown" ]; then
588     CPUName=$(uname -m)
589 fi
590
591 case $CPUName in
592     i686)
593         echo "Unsupported CPU $CPUName detected, build might not succeed!"
594         __BuildArch=x86
595         __HostArch=x86
596         ;;
597
598     x86_64)
599         __BuildArch=x64
600         __HostArch=x64
601         ;;
602
603     armv7l)
604         echo "Unsupported CPU $CPUName detected, build might not succeed!"
605         __BuildArch=arm
606         __HostArch=arm
607         ;;
608
609     aarch64)
610         __BuildArch=arm64
611         __HostArch=arm64
612         ;;
613
614     *)
615         echo "Unknown CPU $CPUName detected, configuring as if for x64"
616         __BuildArch=x64
617         __HostArch=x64
618         ;;
619 esac
620
621 # Use uname to determine what the OS is.
622 OSName=$(uname -s)
623 case $OSName in
624     Linux)
625         __BuildOS=Linux
626         __HostOS=Linux
627         ;;
628
629     Darwin)
630         __BuildOS=OSX
631         __HostOS=OSX
632         ;;
633
634     FreeBSD)
635         __BuildOS=FreeBSD
636         __HostOS=FreeBSD
637         ;;
638
639     OpenBSD)
640         __BuildOS=OpenBSD
641         __HostOS=OpenBSD
642         ;;
643
644     NetBSD)
645         __BuildOS=NetBSD
646         __HostOS=NetBSD
647         ;;
648
649     SunOS)
650         __BuildOS=SunOS
651         __HostOS=SunOS
652         ;;
653
654     *)
655         echo "Unsupported OS $OSName detected, configuring as if for Linux"
656         __BuildOS=Linux
657         __HostOS=Linux
658         ;;
659 esac
660
661 __BuildType=Debug
662 __CodeCoverage=
663 __IncludeTests=INCLUDE_TESTS
664
665 # Set the various build properties here so that CMake and MSBuild can pick them up
666 export __ProjectDir="$__ProjectRoot"
667 __SourceDir="$__ProjectDir/src"
668 __PackagesDir="$__ProjectDir/packages"
669 __RootBinDir="$__ProjectDir/bin"
670 __BuildToolsDir="$__ProjectDir/Tools"
671 __DotNetCli="$__ProjectDir/dotnet.sh"
672 __UnprocessedBuildArgs=
673 __CommonMSBuildArgs=
674 __MSBCleanBuildArgs=
675 __UseNinja=0
676 __VerboseBuild=0
677 __SkipRestore=""
678 __SkipNative=0
679 __SkipManaged=0
680 __SkipConfigure=0
681 __SkipGenerateVersion=0
682 __ConfigureOnly=0
683 __CrossBuild=0
684 __ClangMajorVersion=0
685 __ClangMinorVersion=0
686 __GccBuild=0
687 __GccMajorVersion=0
688 __GccMinorVersion=0
689 __NuGetPath="$__PackagesDir/NuGet.exe"
690 __SkipRestorePackages=0
691 __DistroRid=""
692 __cmakeargs=""
693 __PortableLinux=0
694 __msbuildonunsupportedplatform=0
695 __NativeTestIntermediatesDir=
696 __RunTests=0
697 __RebuildTests=0
698 __BuildTestWrappers=1
699 __GenerateLayoutOnly=
700 __GenerateTestHostOnly=
701 __priority1=
702 __BuildTestWrappersOnly=
703 __DoCrossgen=0
704 CORE_ROOT=
705
706 while :; do
707     if [ $# -le 0 ]; then
708         break
709     fi
710
711     lowerI="$(echo $1 | awk '{print tolower($0)}')"
712     case $lowerI in
713         -\?|-h|--help)
714             usage
715             exit 1
716             ;;
717
718         x86)
719             __BuildArch=x86
720             ;;
721
722         x64)
723             __BuildArch=x64
724             ;;
725
726         arm)
727             __BuildArch=arm
728             ;;
729
730         armel)
731             __BuildArch=armel
732             ;;
733
734         arm64)
735             __BuildArch=arm64
736             ;;
737
738         debug)
739             __BuildType=Debug
740             ;;
741
742         checked)
743             __BuildType=Checked
744             ;;
745
746         release)
747             __BuildType=Release
748             ;;
749
750         coverage)
751             __CodeCoverage=Coverage
752             ;;
753
754         cross)
755             __CrossBuild=1
756             ;;
757
758         portablebuild=false)
759             __PortableBuild=0
760             ;;
761
762         portablelinux)
763             if [ "$__BuildOS" == "Linux" ]; then
764                 __PortableLinux=1
765             else
766                 echo "ERROR: portableLinux not supported for non-Linux platforms."
767                 exit 1
768             fi
769             ;;
770
771         verbose)
772             __VerboseBuild=1
773             ;;
774
775         clang3.5|-clang3.5)
776             __ClangMajorVersion=3
777             __ClangMinorVersion=5
778             ;;
779
780         clang3.6|-clang3.6)
781             __ClangMajorVersion=3
782             __ClangMinorVersion=6
783             ;;
784
785         clang3.7|-clang3.7)
786             __ClangMajorVersion=3
787             __ClangMinorVersion=7
788             ;;
789
790         clang3.8|-clang3.8)
791             __ClangMajorVersion=3
792             __ClangMinorVersion=8
793             ;;
794
795         clang3.9|-clang3.9)
796             __ClangMajorVersion=3
797             __ClangMinorVersion=9
798             ;;
799
800         clang4.0|-clang4.0)
801             __ClangMajorVersion=4
802             __ClangMinorVersion=0
803             ;;
804
805         clang5.0|-clang5.0)
806             __ClangMajorVersion=5
807             __ClangMinorVersion=0
808             ;;
809
810         clang6.0|-clang6.0)
811             __ClangMajorVersion=6
812             __ClangMinorVersion=0
813             ;;
814
815         gcc5|-gcc5)
816             __GccMajorVersion=5
817             __GccMinorVersion=
818             __GccBuild=1
819             ;;
820
821         gcc6|-gcc6)
822             __GccMajorVersion=6
823             __GccMinorVersion=
824             __GccBuild=1
825             ;;
826
827         gcc7|-gcc7)
828             __GccMajorVersion=7
829             __GccMinorVersion=
830             __GccBuild=1
831             ;;
832
833         gcc8|-gcc8)
834             __GccMajorVersion=8
835             __GccMinorVersion=
836             __GccBuild=1
837             ;;
838
839         gcc|-gcc)
840             __GccMajorVersion=
841             __GccMinorVersion=
842             __GccBuild=1
843             ;;
844
845         ninja)
846             __UseNinja=1
847             ;;
848
849         runtests)
850             __RunTests=1
851             ;;
852
853         rebuild)
854             __RebuildTests=1
855             ;;
856
857         skipnative|-skipnative)
858             __SkipNative=1
859             ;;
860
861         skipmanaged|-skipmanaged)
862             __SkipManaged=1
863             __BuildTestWrappers=0
864             ;;
865
866         buildtestwrappersonly)
867             __BuildTestWrappersOnly=1
868             ;;
869
870         generatelayoutonly)
871             __GenerateLayoutOnly=1
872             ;;
873
874         generatetesthostonly)
875             __GenerateTestHostOnly=1
876             ;;
877
878         skiprestorepackages)
879             __SkipRestorePackages=1
880             ;;
881
882         crossgen)
883             __DoCrossgen=1
884             ;;
885
886         bindir)
887             if [ -n "$2" ]; then
888                 __RootBinDir="$2"
889                 if [ ! -d $__RootBinDir ]; then
890                     mkdir $__RootBinDir
891                 fi
892                 __RootBinParent=$(dirname $__RootBinDir)
893                 __RootBinName=${__RootBinDir##*/}
894                 __RootBinDir="$(cd $__RootBinParent &>/dev/null && printf %s/%s $PWD $__RootBinName)"
895                 shift
896             else
897                 echo "ERROR: 'bindir' requires a non-empty option argument"
898                 exit 1
899             fi
900             ;;
901
902         msbuildonunsupportedplatform)
903             __msbuildonunsupportedplatform=1
904             ;;
905
906         priority1)
907             __priority1=1
908             __UnprocessedBuildArgs+=("/p:CLRTestPriorityToBuild=1")
909             ;;
910
911         *)
912             __UnprocessedBuildArgs+=("$1")
913             ;;
914     esac
915
916     shift
917 done
918
919 # Get the number of processors available to the scheduler
920 # Other techniques such as `nproc` only get the number of
921 # processors available to a single process.
922 if [ `uname` = "FreeBSD" ]; then
923   __NumProc=`sysctl hw.ncpu | awk '{ print $2+1 }'`
924 elif [ `uname` = "NetBSD" ]; then
925   __NumProc=$(($(getconf NPROCESSORS_ONLN)+1))
926 elif [ `uname` = "Darwin" ]; then
927   __NumProc=$(($(getconf _NPROCESSORS_ONLN)+1))
928 else
929   __NumProc=$(nproc --all)
930 fi
931
932 __CommonMSBuildArgs=("/p:__BuildArch=$__BuildArch" "/p:__BuildType=$__BuildType" "/p:__BuildOS=$__BuildOS")
933
934 # Configure environment if we are doing a verbose build
935 if [ $__VerboseBuild == 1 ]; then
936     export VERBOSE=1
937     __CommonMSBuildArgs+=("/v:detailed")
938 fi
939
940 # Set default clang version
941 if [[ $__ClangMajorVersion == 0 && $__ClangMinorVersion == 0 ]]; then
942     if [[ "$__BuildArch" == "arm" || "$__BuildArch" == "armel" ]]; then
943         __ClangMajorVersion=5
944         __ClangMinorVersion=0
945     else
946         __ClangMajorVersion=3
947         __ClangMinorVersion=9
948     fi
949 fi
950
951 # Set dependent variables
952 __LogsDir="$__RootBinDir/Logs"
953 __MsbuildDebugLogsDir="$__LogsDir/MsbuildDebugLogs"
954
955 # Set the remaining variables based upon the determined build configuration
956 __BinDir="$__RootBinDir/Product/$__BuildOS.$__BuildArch.$__BuildType"
957 __PackagesBinDir="$__BinDir/.nuget"
958 __TestDir="$__ProjectDir/tests"
959 __TestWorkingDir="$__RootBinDir/tests/$__BuildOS.$__BuildArch.$__BuildType"
960 __IntermediatesDir="$__RootBinDir/obj/$__BuildOS.$__BuildArch.$__BuildType"
961 __TestIntermediatesDir="$__RootBinDir/tests/obj/$__BuildOS.$__BuildArch.$__BuildType"
962 __isMSBuildOnNETCoreSupported=0
963 __CrossComponentBinDir="$__BinDir"
964 __CrossCompIntermediatesDir="$__IntermediatesDir/crossgen"
965
966 __CrossArch="$__HostArch"
967 if [ $__CrossBuild == 1 ]; then
968     __CrossComponentBinDir="$__CrossComponentBinDir/$__CrossArch"
969 fi
970 __CrossgenCoreLibLog="$__LogsDir/CrossgenCoreLib_$__BuildOS.$BuildArch.$__BuildType.log"
971 __CrossgenExe="$__CrossComponentBinDir/crossgen"
972
973 isMSBuildOnNETCoreSupported
974
975 # CI_SPECIFIC - On CI machines, $HOME may not be set. In such a case, create a subfolder and set the variable to it.
976 # This is needed by CLI to function.
977 if [ -z "$HOME" ]; then
978     if [ ! -d "$__ProjectDir/temp_home" ]; then
979         mkdir temp_home
980     fi
981     export HOME=$__ProjectDir/temp_home
982     echo "HOME not defined; setting it to $HOME"
983 fi
984
985 # Configure environment if we are doing a cross compile.
986 if [ $__CrossBuild == 1 ]; then
987     export CROSSCOMPILE=1
988     if ! [[ -n "$ROOTFS_DIR" ]]; then
989         export ROOTFS_DIR="$__ProjectRoot/cross/rootfs/$__BuildArch"
990     fi
991 fi
992
993 # init the target distro name
994 initTargetDistroRid
995
996 # Override tool directory
997
998 if [[ (-z "$__GenerateLayoutOnly") && (-z "$__GenerateTestHostOnly") && (-z "$__BuildTestWrappersOnly") ]]; then
999     build_Tests
1000 elif [ ! -z "$__BuildTestWrappersOnly" ]; then
1001     build_test_wrappers
1002 else
1003     generate_layout
1004     if [ ! -z "$__GenerateTestHostOnly" ]; then
1005         generate_testhost
1006     fi
1007 fi
1008
1009 if [ $? -ne 0 ]; then
1010     echo "Failed to build tests"
1011     exit 1
1012 fi
1013
1014 echo "${__MsgPrefix}Test build successful."
1015 echo "${__MsgPrefix}Test binaries are available at ${__TestBinDir}"
1016
1017 __testNativeBinDir=$__IntermediatesDir/tests
1018
1019 if [ $__RunTests -ne 0 ]; then
1020
1021     echo "Run Tests..."
1022
1023     nextCommand="$__TestDir/runtest.sh --testRootDir=$__TestBinDir --coreClrBinDir=$__BinDir --coreFxBinDir=$CORE_ROOT --testNativeBinDir=$__testNativeBinDir"
1024     echo "$nextCommand"
1025     eval $nextCommand
1026
1027     echo "Tests run successful."
1028 else
1029     echo "To run all tests use 'tests/runtests.sh' where:"
1030     echo "    testRootDir      = $__TestBinDir"
1031     echo "    coreClrBinDir    = $__BinDir"
1032     echo "    coreFxBinDir     = $CORE_ROOT"
1033     echo "    testNativeBinDir = $__testNativeBinDir"
1034     echo " -------------------------------------------------- "
1035     echo " Example runtest.sh command"
1036     echo ""
1037     echo " ./tests/runtest.sh --coreOverlayDir=$CORE_ROOT --testNativeBinDir=$__testNativeBinDir --testRootDir=$__TestBinDir --copyNativeTestBin"
1038     echo " -------------------------------------------------- "
1039     echo "To run single test use the following command:"
1040     echo "    bash ${__TestBinDir}/__TEST_PATH__/__TEST_NAME__.sh -coreroot=${CORE_ROOT}"
1041 fi
1042