Add native configurations for SunOS (#34756)
[platform/upstream/dotnet/runtime.git] / eng / native / build-commons.sh
1 #!/usr/bin/env bash
2
3 initTargetDistroRid()
4 {
5     source "$__RepoRootDir/eng/native/init-distro-rid.sh"
6
7     local passedRootfsDir=""
8
9     # Only pass ROOTFS_DIR if cross is specified.
10     if [[ "$__CrossBuild" == 1 ]]; then
11         passedRootfsDir="$ROOTFS_DIR"
12     fi
13
14     initDistroRidGlobal "$__TargetOS" "$__BuildArch" "$__PortableBuild" "$passedRootfsDir"
15 }
16
17 isMSBuildOnNETCoreSupported()
18 {
19     __IsMSBuildOnNETCoreSupported="$__msbuildonunsupportedplatform"
20
21     if [[ "$__IsMSBuildOnNETCoreSupported" == 1 ]]; then
22         return
23     fi
24
25     if [[ "$__SkipManaged" == 1 ]]; then
26         __IsMSBuildOnNETCoreSupported=0
27         return
28     fi
29
30     if [[ ( "$__HostOS" == "Linux" )  && ( "$__HostArch" == "x64" || "$__HostArch" == "arm" || "$__HostArch" == "armel" || "$__HostArch" == "arm64" ) ]]; then
31         __IsMSBuildOnNETCoreSupported=1
32     elif [[ ( "$__HostOS" == "OSX" || "$__HostOS" == "FreeBSD" ) && "$__HostArch" == "x64" ]]; then
33         __IsMSBuildOnNETCoreSupported=1
34     fi
35 }
36
37 setup_dirs()
38 {
39     echo Setting up directories for build
40
41     mkdir -p "$__RootBinDir"
42     mkdir -p "$__BinDir"
43     mkdir -p "$__IntermediatesDir"
44 }
45
46 # Check the system to ensure the right prereqs are in place
47 check_prereqs()
48 {
49     echo "Checking prerequisites..."
50
51     # Check presence of CMake on the path
52     command -v cmake 2>/dev/null || { echo >&2 "Please install cmake before running this script"; exit 1; }
53
54     function version { echo "$@" | awk -F. '{ printf("%d%02d%02d\n", $1,$2,$3); }'; }
55
56     local cmake_version="$(cmake --version | awk '/^cmake version [0-9]+\.[0-9]+\.[0-9]+$/ {print $3}')"
57
58     if [[ "$(version "$cmake_version")" -lt "$(version 3.14.2)" ]]; then
59         echo "Please install CMake 3.14.2 or newer from http://www.cmake.org/download/ or https://apt.kitware.com and ensure it is on your path."; exit 1;
60     fi
61
62     if [[ "$__UseNinja" == 1 ]]; then
63         command -v ninja 2>/dev/null || command -v ninja-build 2>/dev/null || { echo "Unable to locate ninja!"; exit 1; }
64     fi
65 }
66
67 build_native()
68 {
69     platformArch="$1"
70     cmakeDir="$2"
71     tryrunDir="$3"
72     intermediatesDir="$4"
73     message="$5"
74
75     # All set to commence the build
76     echo "Commencing build of \"$message\" for $__TargetOS.$__BuildArch.$__BuildType in $intermediatesDir"
77
78     if [[ "$__UseNinja" == 1 ]]; then
79         generator="ninja"
80         buildTool="$(command -v ninja || command -v ninja-build)"
81     else
82         buildTool="make"
83     fi
84
85     if [[ "$__SkipConfigure" == 0 ]]; then
86         # if msbuild is not supported, then set __SkipGenerateVersion to 1
87         if [[ "$__IsMSBuildOnNETCoreSupported" == 0 ]]; then __SkipGenerateVersion=1; fi
88         # Drop version.c file
89         __versionSourceFile="$intermediatesDir/version.c"
90
91         if [[ ! -z "${__LogsDir}" ]]; then
92             __binlogArg="-bl:\"$__LogsDir/GenNativeVersion_$__TargetOS.$__BuildArch.$__BuildType.binlog\""
93         fi
94
95         if [[ "$__SkipGenerateVersion" == 0 ]]; then
96             "$__RepoRootDir/eng/common/msbuild.sh" /clp:nosummary "$__ArcadeScriptArgs" "$__RepoRootDir"/eng/empty.csproj \
97                                                    /p:NativeVersionFile="$__versionSourceFile" \
98                                                    /t:GenerateNativeVersionFile /restore \
99                                                    $__CommonMSBuildArgs $__binlogArg $__UnprocessedBuildArgs
100             local exit_code="$?"
101             if [[ "$exit_code" != 0 ]]; then
102                 echo "${__ErrMsgPrefix}Failed to generate native version file."
103                 exit "$exit_code"
104             fi
105         else
106             # Generate the dummy version.c, but only if it didn't exist to make sure we don't trigger unnecessary rebuild
107             __versionSourceLine="static char sccsid[] __attribute__((used)) = \"@(#)No version information produced\";"
108             if [[ -e "$__versionSourceFile" ]]; then
109                 read existingVersionSourceLine < "$__versionSourceFile"
110             fi
111             if [[ "$__versionSourceLine" != "$existingVersionSourceLine" ]]; then
112                 echo "$__versionSourceLine" > "$__versionSourceFile"
113             fi
114         fi
115
116         if [[ "$__StaticAnalyzer" == 1 ]]; then
117             scan_build=scan-build
118         fi
119
120         engNativeDir="$__RepoRootDir/eng/native"
121         __CMakeArgs="-DCLR_ENG_NATIVE_DIR=\"$engNativeDir\" $__CMakeArgs"
122         nextCommand="\"$engNativeDir/gen-buildsys.sh\" \"$cmakeDir\" \"$tryrunDir\" \"$intermediatesDir\" $platformArch $__Compiler \"$__CompilerMajorVersion\" \"$__CompilerMinorVersion\" $__BuildType \"$generator\" $scan_build $__CMakeArgs"
123         echo "Invoking $nextCommand"
124         eval $nextCommand
125
126         local exit_code="$?"
127         if [[ "$exit_code" != 0  ]]; then
128             echo "${__ErrMsgPrefix}Failed to generate \"$message\" build project!"
129             exit "$exit_code"
130         fi
131     fi
132
133     # Check that the makefiles were created.
134     if [[ ! -f "$intermediatesDir/CMakeCache.txt" ]]; then
135         echo "${__ErrMsgPrefix}Unable to find generated build files for \"$message\" project!"
136         exit 1
137     fi
138
139     # Build
140     if [[ "$__ConfigureOnly" == 1 ]]; then
141         echo "Finish configuration & skipping \"$message\" build."
142         return
143     fi
144
145     if [[ "$__StaticAnalyzer" == 1 ]]; then
146         pushd "$intermediatesDir"
147
148         buildTool="$SCAN_BUILD_COMMAND -o $__BinDir/scan-build-log $buildTool"
149         echo "Executing $buildTool install -j $__NumProc"
150         "$buildTool" install -j "$__NumProc"
151
152         popd
153     else
154         cmake_command=cmake
155         if [[ "$build_arch" == "wasm" ]]; then
156             cmake_command="emcmake $cmake_command"
157         fi
158
159         echo "Executing $cmake_command --build \"$intermediatesDir\" --target install -j $__NumProc"
160         $cmake_command --build "$intermediatesDir" --target install -j "$__NumProc"
161     fi
162
163     local exit_code="$?"
164     if [[ "$exit_code" != 0 ]]; then
165         echo "${__ErrMsgPrefix}Failed to build \"$message\"."
166         exit "$exit_code"
167     fi
168 }
169
170 usage()
171 {
172     echo "Usage: $0 <options>"
173     echo ""
174     echo "Common Options:"
175     echo ""
176     echo "BuildArch can be: -arm, -armel, -arm64, x64, x86, -wasm"
177     echo "BuildType can be: -debug, -checked, -release"
178     echo "-os: target OS (defaults to running OS)"
179     echo "-bindir: output directory (defaults to $__ProjectRoot/artifacts)"
180     echo "-ci: indicates if this is a CI build."
181     echo "-clang: optional argument to build using clang in PATH (default)."
182     echo "-clangx.y: optional argument to build using clang version x.y."
183     echo "-cmakeargs: user-settable additional arguments passed to CMake."
184     echo "-configureonly: do not perform any builds; just configure the build."
185     echo "-cross: optional argument to signify cross compilation,"
186     echo "        will use ROOTFS_DIR environment variable if set."
187     echo "-gcc: optional argument to build using gcc in PATH."
188     echo "-gccx.y: optional argument to build using gcc version x.y."
189     echo "-msbuildonunsupportedplatform: build managed binaries even if distro is not officially supported."
190     echo "-ninja: target ninja instead of GNU make"
191     echo "-numproc: set the number of build processes."
192     echo "-portablebuild: pass -portablebuild=false to force a non-portable build."
193     echo "-skipconfigure: skip build configuration."
194     echo "-skipgenerateversion: disable version generation even if MSBuild is supported."
195     echo "-verbose: optional argument to enable verbose build output."
196     echo ""
197     echo "Additional Options:"
198     echo ""
199     for i in "${!usage_list[@]}"; do
200         echo "${usage_list[${i}]}"
201     done
202     echo ""
203     exit 1
204 }
205
206 source "$__RepoRootDir/eng/native/init-os-and-arch.sh"
207
208 __BuildArch=$arch
209 __HostArch=$arch
210 __TargetOS=$os
211 __HostOS=$os
212 __BuildOS=$os
213
214 __msbuildonunsupportedplatform=0
215
216 while :; do
217     if [[ "$#" -le 0 ]]; then
218         break
219     fi
220
221     lowerI="$(echo "$1" | awk '{print tolower($0)}')"
222     case "$lowerI" in
223         -\?|-h|--help)
224             usage
225             exit 1
226             ;;
227
228         arm|-arm)
229             __BuildArch=arm
230             ;;
231
232         arm64|-arm64)
233             __BuildArch=arm64
234             ;;
235
236         armel|-armel)
237             __BuildArch=armel
238             ;;
239
240         bindir|-bindir)
241             if [[ -n "$2" ]]; then
242                 __RootBinDir="$2"
243                 if [[ ! -d "$__RootBinDir" ]]; then
244                     mkdir "$__RootBinDir"
245                 fi
246                 __RootBinParent=$(dirname "$__RootBinDir")
247                 __RootBinName="${__RootBinDir##*/}"
248                 __RootBinDir="$(cd "$__RootBinParent" &>/dev/null && printf %s/%s "$PWD" "$__RootBinName")"
249                 shift
250             else
251                 echo "ERROR: 'bindir' requires a non-empty option argument"
252                 exit 1
253             fi
254             ;;
255
256         checked|-checked)
257             __BuildType=Checked
258             ;;
259
260         ci|-ci)
261             __ArcadeScriptArgs="--ci"
262             __ErrMsgPrefix="##vso[task.logissue type=error]"
263             ;;
264
265         clang*|-clang*)
266                 __Compiler=clang
267                 # clangx.y or clang-x.y
268                 version="$(echo "$lowerI" | tr -d '[:alpha:]-=')"
269                 parts=(${version//./ })
270                 __CompilerMajorVersion="${parts[0]}"
271                 __CompilerMinorVersion="${parts[1]}"
272                 if [[ -z "$__CompilerMinorVersion" && "$__CompilerMajorVersion" -le 6 ]]; then
273                     __CompilerMinorVersion=0;
274                 fi
275             ;;
276
277         cmakeargs|-cmakeargs)
278             if [[ -n "$2" ]]; then
279                 __CMakeArgs="$2 $__CMakeArgs"
280                 shift
281             else
282                 echo "ERROR: 'cmakeargs' requires a non-empty option argument"
283                 exit 1
284             fi
285             ;;
286
287         configureonly|-configureonly)
288             __ConfigureOnly=1
289             __SkipMSCorLib=1
290             __SkipNuget=1
291             ;;
292
293         cross|-cross)
294             __CrossBuild=1
295             ;;
296
297         debug|-debug)
298             __BuildType=Debug
299             ;;
300
301         gcc*|-gcc*)
302                 __Compiler=gcc
303                 # gccx.y or gcc-x.y
304                 version="$(echo "$lowerI" | tr -d '[:alpha:]-=')"
305                 parts=(${version//./ })
306                 __CompilerMajorVersion="${parts[0]}"
307                 __CompilerMinorVersion="${parts[1]}"
308             ;;
309
310         msbuildonunsupportedplatform|-msbuildonunsupportedplatform)
311             __msbuildonunsupportedplatform=1
312             ;;
313
314         ninja|-ninja)
315             __UseNinja=1
316             ;;
317
318         numproc|-numproc)
319             if [[ -n "$2" ]]; then
320               __NumProc="$2"
321               shift
322             else
323               echo "ERROR: 'numproc' requires a non-empty option argument"
324               exit 1
325             fi
326             ;;
327
328         portablebuild=false|-portablebuild=false)
329             __PortableBuild=0
330             ;;
331
332         release|-release)
333             __BuildType=Release
334             ;;
335
336         skipconfigure|-skipconfigure)
337             __SkipConfigure=1
338             ;;
339
340         skipgenerateversion|-skipgenerateversion)
341             __SkipGenerateVersion=1
342             ;;
343
344         verbose|-verbose)
345             __VerboseBuild=1
346             ;;
347
348         x86|-x86)
349             __BuildArch=x86
350             ;;
351
352         x64|-x64)
353             __BuildArch=x64
354             ;;
355
356         wasm|-wasm)
357             __BuildArch=wasm
358             ;;
359
360         os|-os)
361             if [[ -n "$2" ]]; then
362                 __TargetOS="$2"
363                 shift
364             else
365                 echo "ERROR: 'os' requires a non-empty option argument"
366                 exit 1
367             fi
368             ;;
369
370         *)
371             handle_arguments "$1" "$2"
372             if [[ "$__ShiftArgs" == 1 ]]; then
373                 shift
374                 __ShiftArgs=0
375             fi
376             ;;
377     esac
378
379     shift
380 done
381
382 # Get the number of processors available to the scheduler
383 # Other techniques such as `nproc` only get the number of
384 # processors available to a single process.
385 platform=$(uname)
386 if [[ "$platform" == "FreeBSD" ]]; then
387   __NumProc=$(sysctl hw.ncpu | awk '{ print $2+1 }')
388 elif [[ "$platform" == "NetBSD" || "$platform" == "SunOS" ]]; then
389   __NumProc=$(($(getconf NPROCESSORS_ONLN)+1))
390 elif [[ "$platform" == "Darwin" ]]; then
391   __NumProc=$(($(getconf _NPROCESSORS_ONLN)+1))
392 else
393   __NumProc=$(nproc --all)
394 fi
395
396 __CommonMSBuildArgs="/p:TargetArchitecture=$__BuildArch /p:Configuration=$__BuildType /p:TargetOS=$__TargetOS /nodeReuse:false $__OfficialBuildIdArg $__SignTypeArg $__SkipRestoreArg"
397
398 # Configure environment if we are doing a verbose build
399 if [[ "$__VerboseBuild" == 1 ]]; then
400     VERBOSE=1
401     export VERBOSE
402     __CommonMSBuildArgs="$__CommonMSBuildArgs /v:detailed"
403 fi
404
405 if [[ "$__PortableBuild" == 0 ]]; then
406     __CommonMSBuildArgs="$__CommonMSBuildArgs /p:PortableBuild=false"
407 fi
408
409 # Configure environment if we are doing a cross compile.
410 if [[ "$__CrossBuild" == 1 ]]; then
411     CROSSCOMPILE=1
412     export CROSSCOMPILE
413     if [[ ! -n "$ROOTFS_DIR" ]]; then
414         ROOTFS_DIR="$__RepoRootDir/.tools/rootfs/$__BuildArch"
415         export ROOTFS_DIR
416     fi
417 fi
418
419 # init the target distro name
420 initTargetDistroRid
421
422 # Init if MSBuild for .NET Core is supported for this platform
423 isMSBuildOnNETCoreSupported