Merged in Oblivium/librepilot/LP-533_Fix_serial_receiver_input_on_Sparky2 (pull reque...
[librepilot.git] / tool_install.sh
blob670b35730960de1cf1d8283903b32ccbec336628
1 #!/bin/bash
3 # Exit if an error or an unset variable
4 set -e -u
6 # make sure unmatched glob gives empty
7 shopt -s nullglob
9 root_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
10 tools_dir=${TOOLS_DIR:-${root_dir}/tools}
11 downloads_dir=${DL_DIR:-${root_dir}/downloads}
12 tool_overrides_dir=$root_dir/make/tool_install
14 batch=${BATCH:-false}
15 force=false
16 remove=false
17 includes=true
19 for arg in "${@:1}"
21 [ "$arg" = "-r" ] && remove=true
22 [ "$arg" = "-f" ] && force=true
23 [ "$arg" = "-n" ] && includes=false
25 done
27 tool=${@: -1}
29 uname=$(uname)
30 if [[ "$uname" != [LD]* ]]
31 then
32 uname=Windows
36 # Batch mode
37 if $batch
38 then
39 CURL_OPTIONS=(--silent -L)
40 else
41 CURL_OPTIONS=(-L)
44 ################################################################################
45 # Helper functions
46 ################################################################################
48 function exit_error
50 error=$?
51 echo "${@}"
52 exit $error
55 ## Downloads a file if it doesn't exist
56 #1 URL
57 #2 Output filename (optional)
58 #3+ Additional options to pass to curl
59 ## Sets:
60 #out_file: path of the downloaded file
61 function download_file
63 out_file="$downloads_dir/${2:-$(basename "$1")}"
65 if ! [ -f "$out_file" ]
66 then
67 mkdir -p "$downloads_dir" && \
68 cd "$downloads_dir" && \
69 echo "Downloading $1" && \
70 curl "${CURL_OPTIONS[@]}" "${@:3}" -o "$out_file" "$1"
74 ## Unzips a file
75 #1 The file to unzip
76 #2 The output directory
77 function zip_extract
79 unzip -q "$1" -d "$2"
82 ## Extracts a 7zip file
83 #1 The file to extract
84 #2 The output directory
85 function sevenzip_extract
87 if [ "$uname" = Windows ]
88 then
89 7za.exe x -o"$2" "$1"
90 else
91 7zr x -o"$2" "$1"
95 ## Extracts a tar file
96 #1 The file to extract
97 #2 The output directory
98 function tar_extract
100 tar -xf "$1" -C "$2"
103 ## Extracts a file
104 #1 File to extract
105 #2 Extract directory (optional)
106 no_extract=false # Optional
107 ## Sets:
108 #out_dir: directory the file was extracted into
109 function extract_file
111 out_dir="${2:-.}"
113 echo "Extracting $1"
115 mkdir -p "$out_dir" && \
116 case "$1" in
117 *.zip)
118 zip_extract "$1" "$out_dir"
120 *.7z)
121 sevenzip_extract "$1" "$out_dir"
123 *.tar*)
124 tar_extract "$1" "$out_dir"
127 if $no_extract
128 then
129 cp "$1" "$out_dir"
130 else
131 return 1
133 esac
136 ## Verifies an md5 file
137 #1 md5 file
138 #2 file to check
139 function md5_verify_file
141 if [ "$uname" = Darwin ]
142 then
143 [[ "$(md5 "$2")" = *"$(awk '{print $1}' "$1")"* ]]
144 else
145 ( cd "$downloads_dir" && md5sum -c "$1" )
149 ################################################################################
150 # Default functions
151 ################################################################################
153 function validate_target { false; }
155 function remove
157 rm -rf "$tools_dir/$tool_install_name"
158 rm -f "$tools_dir/$tool".{sh,mk}
161 declare -a depends=()
162 function install_deps
164 # Workaround for set -u and empty array
165 for dep in "${depends[@]:+${depends}}"
167 BATCH="$batch" "${BASH_SOURCE[0]}" "$dep"
168 done && \
169 source_includes
172 ## Downloads and verifies the tool
173 ## Required:
174 #tool_url: the url to download the tool from
175 ## Optional:
176 #tool_md5
177 #tool_md5_url
178 function download_and_verify
180 verified=true
181 download_file "$tool_url" && \
182 downloaded_file=$out_file && \
183 if [ -n "${tool_md5_url:-}" ]
184 then
185 download_file "$tool_md5_url" "$(basename "$downloaded_file").md5" --silent && \
186 if ! md5_verify_file "$out_file" "$downloaded_file"
187 then
188 mv -f "$downloaded_file"{,.rej} && \
189 mv -f "$downloaded_file".md5{,.rej} && \
190 verified=false
192 elif [ -n "${tool_md5:-}" ]
193 then
194 if [[ "$tool_md5"* != "$(cd "$downloads_dir" && md5sum "$downloaded_file")" ]]
195 then
196 mv -f "$downloaded_file"{,.rej} && \
197 verified=false
199 fi && \
200 $verified
203 function tool_is_installed { [ -e "$full_tool_install_name" ] || which "$tool" &>/dev/null; }
205 ## Downloads and extracts the tool
206 ## Required:
207 #tool_url: the url to download the tool from
208 #tool_install_name: the directory or file the tool will be installed as
209 ## Optional:
210 #tool_extract_dir: Directory to extract into (useful if build required)
211 function download_and_extract
213 local full_tool_install_name="$tools_dir/$tool_install_name"
214 if ! tool_is_installed || $force
215 then
216 download_and_verify || exit_error "Failed to verify $downloaded_file"
217 rm -rf "$full_tool_install_name" && \
218 extract_file "$downloaded_file" "${tool_extract_dir:-$tools_dir}"
222 function build_and_install { true; } # Most tools don't need this step
224 ## Write modules that are included by this script and make
225 ## Optional:
226 bin_dir=""
227 bin_subdir="" #
228 module_file=$tool
229 function write_modules
231 if [ -n "$bin_subdir" ]
232 then
233 bin_dir="$tools_dir/$tool_install_name/$bin_subdir"
236 if [ -n "$bin_dir" ]
237 then
238 local new_path="$bin_dir"':${PATH}'
239 # Write shell module file
240 echo 'if [[ ":$PATH:" != *":'"$bin_dir"':"* ]]; then export PATH='"$new_path"'; fi' > "$tools_dir/$module_file".sh
241 # Write make module file
242 echo 'ifeq ($(findstring :'"$bin_dir"':,:$(PATH):),)' > "$tools_dir/$module_file".mk
243 echo "export PATH := $new_path" >> "$tools_dir/$module_file".mk
244 echo "endif" >> "$tools_dir/$module_file".mk
249 function source_includes
251 if $includes
252 then
253 for module in "$tools_dir"/*.sh
255 source "$module"
256 done
260 ################################################################################
261 # Peform tool install
262 ################################################################################
263 source_includes || exit_error "failed to source includes"
265 source "$tool_overrides_dir/${tool}.sh"
267 if $remove
268 then
269 remove || exit_error "Failed to remove ${tool}"
270 else
271 validate_target || exit_error "${tool} is not a valid target"
273 install_deps || exit_error "Failed to install dependencies for ${tool}"
275 download_and_extract || exit_error "Failed to download and extract ${tool}"
277 build_and_install || exit_error "Failed to build and install ${tool}"
279 write_modules || exit_error "Failed to write modules for ${tool}"