Update Tizen CI docker image
[platform/upstream/dotnet/runtime.git] / tools-local / scripts / arm32_ci_script.sh
1 #!/bin/bash
2
3 #Usage message
4 function usage {
5     echo 'ARM Emulator Cross Build Script'
6     echo 'This script cross builds core-setup source'
7     echo ''
8     echo 'Typical usage:'
9     echo '    core-setup source is at ~/core-setup'
10     echo '$ cd ~/core-setup'
11     echo '$ ./scripts/arm32_ci_script.sh'
12     echo '    --buildConfig=Release'
13     echo '    --armel'
14     echo '    --verbose'
15     echo ''
16     echo 'Required Arguments:'
17     echo '    --buildConfig=<config>             : The value of config should be either Debug or Release'
18     echo '                                         Any other value is not accepted'
19     echo 'Optional Arguments:'
20     echo '    --mode=<mode>                      : docker (default) or emulator'
21     echo '    --arm                              : Build as arm (default)'
22     echo '    --armel                            : Build as armel'
23     echo '    --linuxCodeName=<name>             : Code name for Linux: For arm, trusty (default) and xenial. For armel, tizen'
24     echo '    --skipRootFS                       : Skip building rootfs'
25     echo '    --emulatorPath=<path>              : Path of the emulator folder (without ending /)'
26     echo '                                         <path>/platform/rootfs-t30.ext4 should exist'
27     echo '    --mountPath=<path>                 : The desired path for mounting the emulator rootfs (without ending /)'
28     echo '                                         This path is created if not already present'
29     echo '    -v --verbose                       : Build made verbose'
30     echo '    -h --help                          : Prints this usage message and exits'
31     echo ''
32     echo 'Any other argument triggers an error and this usage message is displayed'
33     exit 1
34 }
35
36 #Display error message and exit
37 function exit_with_error {
38     set +x
39
40     local errorMessage="$1"
41     local printUsage=$2
42
43     echo "ERROR: $errorMessage"
44     if [ "$printUsage" == "true" ]; then
45         echo ''
46         usage
47     fi
48     exit 1
49 }
50
51 #Exit if input string is empty
52 function exit_if_empty {
53     local inputString="$1"
54     local errorMessage="$2"
55     local printUsage=$3
56
57     if [ -z "$inputString" ]; then
58         exit_with_error "$errorMessage" $printUsage
59     fi
60 }
61
62 #Exit if the input path does not exist
63 function exit_if_path_absent {
64     local path="$1"
65     local errorMessage="$2"
66     local printUsage=$3
67
68     if [ ! -f "$path" -a ! -d "$path" ]; then
69         exit_with_error "$errorMessage" $printUsage
70     fi
71 }
72
73 #Check if the git changes were reverted completely
74 function check_git_head {
75     local currentGitHead=`git rev-parse --verify HEAD`
76
77     if [[ "$__initialGitHead" != "$currentGitHead" ]]; then
78         exit_with_error "Some changes made to the code history were not completely reverted. Intial Git HEAD: $__initialGitHead, current Git HEAD: $currentGitHead" false
79     fi
80 }
81
82 function unmount_rootfs {
83     local rootfsFolder="$1"
84
85     #Check if there are any open files in this directory.
86     if [ -d $rootfsFolder ]; then
87         #If we find information about the file
88         if sudo lsof +D $rootfsFolder; then
89             (set +x; echo 'See above for lsof information. Continuing with the build.')
90         fi
91     fi
92
93     if mountpoint -q -- "$rootfsFolder"; then
94         sudo umount "$rootfsFolder"
95     fi
96 }
97
98 #Unmount the emulator file systems
99 function unmount_emulator {
100     (set +x; echo 'Unmounting emulator...')
101
102     #Unmount all the mounted emulator file systems
103     unmount_rootfs "$__ARMRootfsMountPath/proc"
104     unmount_rootfs "$__ARMRootfsMountPath/dev/pts"
105     unmount_rootfs "$__ARMRootfsMountPath/dev"
106     unmount_rootfs "$__ARMRootfsMountPath/run/shm"
107     unmount_rootfs "$__ARMRootfsMountPath/sys"
108     unmount_rootfs "$__ARMRootfsMountPath"
109 }
110
111 #Clean the changes made to the environment by the script
112 function clean_env {
113     #Check for revert of git changes
114     check_git_head
115 }
116
117 #Trap Ctrl-C and handle it
118 function handle_ctrl_c {
119     set +x
120
121     echo 'ERROR: Ctrl-C handled. Script aborted before complete execution.'
122
123     exit 1
124 }
125 trap handle_ctrl_c INT
126
127 #Trap Exit and handle it
128 function handle_exit {
129     set +x
130
131     echo 'The script is exited. Cleaning environment..'
132
133     clean_env
134  }
135 trap handle_exit EXIT
136
137 #Mount with checking to be already existed
138 function mount_with_checking {
139     set +x
140     local options="$1"
141     local from="$2"
142     local rootfsFolder="$3"
143
144     if mountpoint -q -- "$rootfsFolder"; then
145         (set +x; echo "$rootfsFolder is already mounted.")
146     else {
147         (set -x; sudo mount $options "$from" "$rootfsFolder")
148     }
149     fi
150 }
151
152 #Mount emulator to the target mount path
153 function mount_emulator {
154     #Check if the mount path exists and create if neccessary
155     if [ ! -d "$__ARMRootfsMountPath" ]; then
156         sudo mkdir -p "$__ARMRootfsMountPath"
157     fi
158
159     set +x
160     mount_with_checking "" "$__ARMEmulPath/platform/$__ARMRootfsImageBase" "$__ARMRootfsMountPath"
161     mount_with_checking "-t proc" "/proc"    "$__ARMRootfsMountPath/proc"
162     mount_with_checking "-o bind" "/dev/"    "$__ARMRootfsMountPath/dev"
163     mount_with_checking "-o bind" "/dev/pts" "$__ARMRootfsMountPath/dev/pts"
164     mount_with_checking "-t tmpfs" "shm"     "$__ARMRootfsMountPath/run/shm"
165     mount_with_checking "-o bind" "/sys"     "$__ARMRootfsMountPath/sys"
166 }
167
168 # Cross builds core-setup using Docker image
169 function cross_build_core_setup_with_docker {
170     __currentWorkingDirectory=`pwd`
171
172     # Check build configuration and choose Docker image
173     if [ "$__buildArch" == "arm" ]; then
174         # TODO: For arm, we are going to embed RootFS inside Docker image.
175         case $__linuxCodeName in
176         trusty)
177             __dockerImage=" microsoft/dotnet-buildtools-prereqs:ubuntu-14.04-cross-0cd4667-20172211042239"
178             __runtimeOS="ubuntu.14.04"
179         ;;
180         xenial)
181             __dockerImage=" microsoft/dotnet-buildtools-prereqs:ubuntu-16.04-cross-ef0ac75-20175511035548"
182             __runtimeOS="ubuntu.16.04"
183         ;;
184         *)
185             exit_with_error "ERROR: $__linuxCodeName is not a supported linux name for $__buildArch" false
186         ;;
187         esac
188     elif [ "$__buildArch" == "armel" ]; then
189         # For armel Tizen, we are going to construct RootFS on the fly.
190         case $__linuxCodeName in
191         tizen)
192             __dockerImage=" gbalykov/dotnet-buildtools-prereqs:ubuntu-16.04-cross-e435274-20180426002255-tizen-rootfs-4.0m2"
193             __runtimeOS="tizen.4.0.0"
194         ;;
195         *)
196             echo "ERROR: $__linuxCodeName is not a supported linux name for $__buildArch"
197             exit_with_error "ERROR: $__linuxCodeName is not a supported linux name for $__buildArch" false
198         ;;
199         esac
200     else
201         exit_with_error "ERROR: unknown buildArch $__buildArch" false
202     fi
203     __dockerCmd="sudo docker run --privileged -i --rm -v $__currentWorkingDirectory:/opt/core-setup -w /opt/core-setup $__dockerImage"
204
205     if [ $__skipRootFS == 0 ]; then
206         # Build rootfs
207         __buildRootfsCmd="./cross/build-rootfs.sh $__buildArch $__linuxCodeName --skipunmount"
208
209         (set +x; echo "Build RootFS for $__buildArch $__linuxCodeName")
210         $__dockerCmd $__buildRootfsCmd
211         sudo chown -R $(id -u -n) cross/rootfs
212         __rootfsDir="/opt/core-setup/cross/rootfs/$__buildArch"
213     fi
214
215     # Cross building core-setup with rootfs in Docker
216     __buildCmd="./build.sh --configuration $__buildConfig --env-vars DISABLE_CROSSGEN=1,TARGETPLATFORM=$__buildArch,OUTPUTRID=$__runtimeOS-$__buildArch,CROSS=1,ROOTFS_DIR=$__rootfsDir"
217     $__dockerCmd $__buildCmd
218 }
219
220 #Define script variables
221 __ciMode="docker"
222 __ARMEmulPath="/opt/linux-arm-emulator"
223 __ARMRootfsImageBase="rootfs-u1404.ext4"
224 __ARMRootfsMountPath="/opt/linux-arm-emulator-root"
225 __buildConfig="Release"
226 __verboseFlag=
227 __buildArch="arm"
228 __linuxCodeName="trusty"
229 __skipRootFS=0
230 __rootfsDir=
231 __initialGitHead=`git rev-parse --verify HEAD`
232
233 #Parse command line arguments
234 for arg in "$@"
235 do
236     case $arg in
237     --emulatorPath=*)
238         __ARMEmulPath=${arg#*=}
239         ;;
240     --mountPath=*)
241         __ARMRootfsMountPath=${arg#*=}
242         ;;
243     --buildConfig=*)
244         __buildConfig="$(echo ${arg#*=} | awk '{print tolower($0)}')"
245         if [[ "$__buildConfig" == "release" ]]; then
246             __buildConfig="Release"
247         else
248             if [[ "$__buildConfig" == "debug" ]]; then
249                 __buildConfig="Debug"
250             else
251                 exit_with_error "--buildConfig can be only Debug or Release" true
252             fi
253         fi
254         ;;
255     --mode=*)
256         __ciMode=${arg#*=}
257         ;;
258     --arm)
259         __ARMRootfsImageBase="rootfs-u1404.ext4"
260         __buildArch="arm"
261         __skipRootFS=1
262         __rootfsDir="/crossrootfs/arm"
263         ;;
264     --armel)
265         __ARMRootfsImageBase="rootfs-t30.ext4"
266         __buildArch="armel"
267         __skipRootFS=1
268         __rootfsDir="/crossrootfs/armel.tizen.build"
269         __linuxCodeName="tizen"
270         ;;
271     --linuxCodeName=*)
272         __linuxCodeName=${arg#*=}
273         ;;
274     --skipRootFS)
275         __skipRootFS=1
276         ;;
277     -v|--verbose)
278         __verboseFlag="verbose"
279         ;;
280     -h|--help)
281         usage
282         ;;
283     *)
284         exit_with_error "$arg not a recognized argument" true
285         ;;
286     esac
287 done
288
289 if [[ $__linuxCodeName == "tizen" ]]; then
290     # This case does not support CI build yet.
291     # Will be enabled ASAP.
292     exit 0
293 fi
294
295 #Check if there are any uncommited changes in the source directory as git adds and removes patches
296 if [[ $(git status -s) != "" ]]; then
297    echo 'ERROR: There are some uncommited changes. To avoid losing these changes commit them and try again.'
298    echo ''
299    git status
300    exit 1
301 fi
302
303 exit_if_empty "$__buildConfig" "--buildConfig is a mandatory argument, not provided" true
304 if [ "$__ciMode" == "emulator" ]; then
305     #Check if the compulsory arguments have been presented to the script and if the input paths exist
306     exit_if_empty "$__ARMEmulPath" "--emulatorPath is a mandatory argument, not provided" true
307     exit_if_empty "$__ARMRootfsMountPath" "--mountPath is a mandatory argument, not provided" true
308     exit_if_path_absent "$__ARMEmulPath/platform/$__ARMRootfsImageBase" "Path specified in --emulatorPath does not have the rootfs" false
309
310     __ARMRootfsMountPath="${__ARMRootfsMountPath}_${__buildArch}"
311 fi
312
313 set -x
314 set -e
315
316 ## Begin cross build
317 (set +x; echo "Git HEAD @ $__initialGitHead")
318
319 #Complete the cross build
320 (set +x; echo 'Building core-setup...')
321 if [ "$__ciMode" == "docker" ]; then
322     cross_build_core_setup_with_docker
323 else
324     exit_with_error "Not supported emulator mode"
325 fi
326
327 #Clean the environment
328 (set +x; echo 'Cleaning environment...')
329 clean_env
330
331 (set +x; echo 'Build complete')