Bump zlib to 1.3.1, 1.3 is no longer available.
[harbours.git] / hsct.sh
blob2b609b8dceeac94eb7916c60453faec9ce8f433a
1 #!/bin/sh
4 # Copyright (c) 2013-2017 Vojtech Horky
5 # All rights reserved.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
11 # - Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # - Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # - The name of the author may not be used to endorse or promote products
17 # derived from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 # Calling harbour functions:
32 # These functions are always called in a subshell to "guard" them a little
33 # bit (variables set by the harbour, cd into package directory).
35 # Notice on usage of set -o errexit (set -e)
36 # We want to use that option for the harbour scripts to get rid of the
37 # "|| return 1" at the end of each line.
38 # Obvious solution is to wrap the call like this:
39 # ( set -o errexit; build ) || { hsct_error "..."; return 1; }
40 # This doesn't work because the whole subshell is then part of a ||
41 # operand and thus the set -e is ignored (even if it is a subshell).
42 # See https://groups.google.com/d/msg/gnu.bash.bug/NCK_0GmIv2M/y6RQF1AWUQkJ
43 # Thus, we need to use the following template to get past this:
44 # ( set -o errexit; build; exit $? );
45 # [ $? -eq 0 ] || { hsct_error "..."; return 1; }
47 # Also notice that we never ever call exit from the top-most shell when
48 # leaving after an error. That is to prevent terminating user shell when
49 # this script is sourced ("env" command). It complicates the error handling
50 # a bit but it is more reliable than trying to guess whether we are running
51 # in a subshell or not.
54 HSCT_HOME=`which -- "$0" 2>/dev/null`
55 # Maybe, we are running Bash
56 [ -z "$HSCT_HOME" ] && HSCT_HOME=`which -- "$BASH_SOURCE" 2>/dev/null`
57 HSCT_HOME=`dirname -- "$HSCT_HOME"`
58 HSCT_HOME=`cd $HSCT_HOME && echo $PWD`
59 HSCT_HSCT="$HSCT_HOME/hsct.sh"
61 HSCT_BUILD_DIR=`pwd`/build
62 HSCT_INCLUDE_DIR=`pwd`/include
63 HSCT_LIB_DIR=`pwd`/libs
64 HSCT_DIST_DIR="`pwd`/dist/"
65 HSCT_ARCHIVE_DIR="`pwd`/archives/"
66 HSCT_CACHE_DIR=`pwd`/helenos
68 # Print short help.
69 # Does not exit the whole script.
70 hsct_usage() {
71 echo "Usage:"
72 echo " $1 action [package]"
73 echo " Action can be one of following:"
74 echo " clean Clean build directory to save space."
75 echo " distclean Prepare for recompilation (clean flag files)."
76 echo " fetch Fetch sources (e.g. download from homepage)."
77 echo " build Build given package."
78 echo " package Save installable files to allow cleaning."
79 echo " install Install to uspace/dist of HelenOS."
80 echo " archive Create tarball instead of installing."
81 echo " $1 init [/path/to/HelenOS] [profile]"
82 echo " Initialize current directory as coastline build directory".
83 echo " Full path has to be provided to the HelenOS source tree."
84 echo " If profile is specified, forcefully rebuild to specified profile."
85 echo " If no argument is provided, path to HelenOS source tree is"
86 echo " read from the HELENOS_ROOT environment variable."
87 echo " $1 help"
88 echo " Display this help and exit."
91 # Print high-level information message.
92 hsct_info() {
93 echo ">>>" "$@" >&2
96 # Print lower-level information message (additional info after hsct_info).
97 hsct_info2() {
98 echo " ->" "$@" >&2
101 # Print information message from HARBOUR script.
102 msg() {
103 hsct_info "$@"
106 # Print high-level error message.
107 hsct_error() {
108 echo "[hsct]:" "Error:" "$@" >&2
111 # Print additional details to the error message.
112 hsct_error2() {
113 echo "[hsct]:" " -> " "$@" >&2
116 # Run a command but print it first.
117 hsct_run_echo() {
118 echo -n "[hsct]: "
119 for ___i in "$@"; do
120 echo -n "$___i" | sed -e 's#"#\\"#g' -e 's#.*#"&" #'
121 done
122 echo
123 "$@"
126 # Run comman from HARBOUR script and print it as well.
127 run() {
128 hsct_run_echo "$@"
131 hsct_process_harbour_opts() {
132 HSCT_OPTS_NO_DEPENDENCY_BUILDING=false
133 HSCT_OPTS_NO_FILE_DOWNLOADING=false
134 HSCT_OPTS_FORCE=false
135 HSCT_HARBOUR_NAME=""
137 while [ "$#" -ne 0 ]; do
138 case "$1" in
139 --no-deps)
140 HSCT_OPTS_NO_DEPENDENCY_BUILDING=true
142 --no-fetch)
143 HSCT_OPTS_NO_FILE_DOWNLOADING=true
145 --force)
146 HSCT_OPTS_FORCE=true
148 --*)
149 hsct_error "Unknown option $1."
150 return 60
153 if [ -z "$HSCT_HARBOUR_NAME" ]; then
154 HSCT_HARBOUR_NAME="$1"
155 else
156 hsct_error "Only one package name allowed."
157 return 61
160 esac
161 shift
162 done
164 return 0
167 # Fetch all the specified files in the HARBOUR
168 hsct_fetch() {
169 mkdir -p "$HSCT_SOURCES_DIR"
170 hsct_info "Fetching sources..."
171 for _src in $shipsources; do
172 _scheme=`echo "$_src" | cut -d: -f 1`
173 if [ "$_scheme" = "git" ]; then
174 _filename=`echo "$_src" | cut -d: -f 2`
175 _rev=`echo "$_src" | cut -d: -f 3`
176 _url=`echo "$_src" | cut -d: -f 4-`
177 else
178 _filename=`basename "$_src"`
179 _url="$_src"
181 echo "filename:'$_filename' url:'$_url'"
182 if [ "$_filename" = "$_url" ]; then
183 continue
185 if ! [ -r "$HSCT_SOURCES_DIR/$_filename" ]; then
186 if $HSCT_OPTS_NO_FILE_DOWNLOADING; then
187 hsct_error "File $_filename missing, cannot continue."
188 hsct_error2 "Build without --no-fetch."
189 return 62
192 hsct_info2 "Fetching $_filename..."
193 # Remove the file even on Ctrl-C when fetching
194 trap "rm -f \"$HSCT_SOURCES_DIR/$_filename\"; echo" SIGINT SIGQUIT
195 if [ "$_scheme" = "git" ]; then
196 # Clone the repository
197 if ! git clone "$_url" "$HSCT_SOURCES_DIR/$_filename"; then
198 rm -f "$HSCT_SOURCES_DIR/$_filename"
199 hsct_error "Failed to fetch $_url."
200 return 63
202 # Check out the specified revision
203 if [ -n "$_rev" ]; then
204 prevdir="$(pwd)"
205 cd "$HSCT_SOURCES_DIR/$_filename"
206 if ! git checkout "$_rev" 2>/dev/null; then
207 rm -rf "$HSCT_SOURCES_DIR/$_filename"
208 hsct_error "Failed to check out revision $_rev."
209 return 63
211 cd "$prevdir"
213 else
214 if [ "$_scheme" = "http" ]; then
215 # If we request an insecure download anyway, don't check certificate after redirection.
216 # This works around a problem with fdlibm download as of July 2020.
217 if ! wget $HSCT_WGET_OPTS --no-check-certificate "$_url" -O "$HSCT_SOURCES_DIR/$_filename"; then
218 rm -f "$HSCT_SOURCES_DIR/$_filename"
219 hsct_error "Failed to fetch $_url."
220 return 63
222 else
223 if ! wget $HSCT_WGET_OPTS "$_url" -O "$HSCT_SOURCES_DIR/$_filename"; then
224 rm -f "$HSCT_SOURCES_DIR/$_filename"
225 hsct_error "Failed to fetch $_url."
226 return 63
230 trap - SIGINT SIGQUIT
232 # TODO - check MD5
233 done
234 return 0
237 # Remove the build directory of given package and enable rebuild
238 # of the package.
239 hsct_distclean() {
240 hsct_info "Cleaning build directory and flag files..."
241 rm -rf "$HSCT_BUILD_DIR/$shipname"
242 rm -f "$HSCT_BUILD_DIR/${shipname}.built"
243 rm -f "$HSCT_BUILD_DIR/${shipname}.packaged"
246 # Remove the build directory of given package.
247 hsct_clean() {
248 if [ -e "$HSCT_BUILD_DIR/${shipname}.built" ]; then
249 if ! [ -e "$HSCT_BUILD_DIR/${shipname}.packaged" ]; then
250 # Built but not packaged? If we remove the build directory
251 # we will not be able to package.
252 if ! $HSCT_OPTS_FORCE; then
253 hsct_error "Cannot clean when built but not packaged."
254 hsct_error2 "Use distclean or --force if you know what you are doing."
255 return 51
259 hsct_info "Cleaning build directory..."
260 rm -rf "$HSCT_BUILD_DIR/$shipname/"
264 # Build the package.
265 hsct_build() {
266 mkdir -p "$HSCT_BUILD_DIR/$shipname"
267 if [ -e "$HSCT_BUILD_DIR/${shipname}.built" ]; then
268 hsct_info "No need to build $shipname."
269 return 0
272 # Check for prerequisities
273 for tug in $shiptugs; do
274 if ! [ -e "$HSCT_BUILD_DIR/${tug}.packaged" ]; then
275 if $HSCT_OPTS_NO_DEPENDENCY_BUILDING; then
276 hsct_error "Dependency $tug not built, cannot continue."
277 hsct_error2 "Build $tug first or run without --no-deps."
278 return 64
280 hsct_info "Need to build $tug first."
281 hsct_info2 "Running $HSCT_HSCT package $tug"
283 $HSCT_HSCT package $tug
284 exit $?
286 if [ $? -ne 0 ]; then
287 hsct_error "Failed to package dependency $tug."
288 hsct_error2 "Cannot continue building $shipname."
289 return 65
291 hsct_info2 "Back from building $tug."
293 done
295 hsct_fetch || return $?
297 for _src in $shipsources; do
298 _scheme=`echo "$_src" | cut -d: -f 1`
299 if [ "$_scheme" = "git" ]; then
300 _filename=`echo "$_src" | cut -d: -f 2`
301 _origin="$HSCT_SOURCES_DIR/$_filename"
302 cp -r "$_origin" "$HSCT_BUILD_DIR/$shipname/$_filename"
303 else
304 _url="$_src"
305 _filename=`basename "$_url"`
306 if [ "$_filename" = "$_url" ]; then
307 _origin="$HSCT_HOME/$shipname/$_filename"
308 else
309 _origin="$HSCT_SOURCES_DIR/$_filename"
312 ln -srf "$_origin" "$HSCT_BUILD_DIR/$shipname/$_filename"
314 done
317 cd "$HSCT_BUILD_DIR/$shipname/"
318 hsct_info "Building..."
319 set -o errexit
320 build
321 exit $?
323 if [ $? -ne 0 ]; then
324 hsct_error "Build failed!"
325 return 66
327 touch "$HSCT_BUILD_DIR/${shipname}.built"
328 return 0
331 # Pseudo-installation - copy from build directory to "my" directory, copy libraries
332 hsct_package() {
333 mkdir -p "$HSCT_INCLUDE_DIR" || { hsct_error "Failed to create include directory."; return 67; }
334 mkdir -p "$HSCT_LIB_DIR" || { hsct_error "Failed to create library directory."; return 67; }
335 mkdir -p "$HSCT_MY_DIR" || { hsct_error "Failed to create package directory."; return 67; }
337 if [ -e "$HSCT_BUILD_DIR/${shipname}.packaged" ]; then
338 hsct_info "No need to package $shipname."
339 return 0;
342 hsct_build || return $?
345 cd "$HSCT_BUILD_DIR/$shipname/"
346 hsct_info "Packaging..."
347 set -o errexit
348 package
349 exit $?
351 if [ $? -ne 0 ]; then
352 hsct_error "Packaging failed!"
353 return 68
355 touch "$HSCT_BUILD_DIR/${shipname}.packaged"
356 return 0
359 # Install the package to HelenOS source tree (to uspace/overlay).
360 hsct_install() {
361 hsct_package || return $?
363 hsct_info "Installing..."
364 if ls "$HSCT_MY_DIR"/* &>/dev/null; then
365 mkdir -p "$HSCT_OVERLAY"
366 cp -v -r -L "$HSCT_MY_DIR"/* "$HSCT_OVERLAY" || return 69
367 hsct_info2 "Do not forget to rebuild the image."
368 else
369 hsct_info2 "Note: nothing to install."
371 return 0
374 # Create tarball to allow redistribution of the build packages
375 hsct_archive() {
376 hsct_package || return $?
378 hsct_info "Creating the archive..."
379 mkdir -p "$HSCT_ARCHIVE_DIR"
381 set -o errexit
382 cd "$HSCT_DIST_DIR/$shipname"
383 case "$HSCT_FORMAT" in
384 tar.gz)
385 tar czf "$HSCT_ARCHIVE_DIR/$shipname.tar.gz" .
387 tar.xz)
388 tar cJf "$HSCT_ARCHIVE_DIR/$shipname.tar.xz" .
391 hsct_info "Unknown archive_format $HSCT_FORMAT."
392 exit 71
394 esac
396 if [ $? -ne 0 ]; then
397 hsct_error "Archiving failed!"
398 return 72
401 return 0
404 hsct_load_config() {
405 # Defaults
406 HSCT_CONFIG="./config.sh"
407 HSCT_WGET_OPTS=
408 HSCT_SOURCES_DIR=`pwd`/sources
409 HSCT_FORMAT="tar.xz"
410 HSCT_PARALLELISM=`nproc`
411 HELENOS_ROOT=
413 if [ -e "$HSCT_CONFIG" ]; then
414 . $HSCT_CONFIG
418 hsct_save_config() {
419 echo "HSCT_WGET_OPTS=\"${HSCT_WGET_OPTS}\"" >> "${HSCT_CONFIG}.new"
420 echo "HSCT_SOURCES_DIR=\"${HSCT_SOURCES_DIR}\"" >> "${HSCT_CONFIG}.new"
421 echo "HSCT_FORMAT=\"${HSCT_FORMAT}\"" >> "${HSCT_CONFIG}.new"
422 echo "HSCT_PARALLELISM=\"${HSCT_PARALLELISM}\"" >> "${HSCT_CONFIG}.new"
423 echo "HELENOS_ROOT=\"${HELENOS_ROOT}\"" >> "${HSCT_CONFIG}.new"
424 mv "${HSCT_CONFIG}.new" "${HSCT_CONFIG}"
427 # Update after changes in HelenOS itself
428 hsct_update() {
429 EXPORT_DIR=`pwd`/helenos
432 cd helenos_build
433 hsct_info "Exporting libraries and header files."
434 env DESTDIR="$EXPORT_DIR" ninja export-dev
437 if [ $? -ne 0 ]; then
438 hsct_error "Failed to export development files."
439 return 75
443 # Initialize current directory for coastline building.
444 hsct_init() {
445 hsct_load_config
447 _root_dir="$1"
448 profile="$2"
450 if [ -z "$_root_dir" ]; then
451 # Try to get HELENOS_ROOT from the environment if not specified.
452 _root_dir="$HELENOS_ROOT"
455 if [ -z "$_root_dir" ]; then
456 hsct_error "HELENOS_ROOT is not set. Either set the environment variable, or specify it on the command line.";
457 return 73
460 _root_dir=`( cd "$_root_dir"; pwd ) 2>/dev/null`
461 if ! [ -e "$_root_dir/HelenOS.config" ]; then
462 hsct_error "$_root_dir does not look like a valid HelenOS directory.";
463 return 74
466 HELENOS_ROOT="$_root_dir"
468 hsct_info "Initializing this build directory."
470 EXPORT_DIR=`pwd`/helenos
471 set -o errexit
473 if [ -z "$profile" ]; then
474 hsct_info2 "Configuring."
475 mkdir -p helenos_build
476 cd helenos_build
477 "$HELENOS_ROOT"/configure.sh
478 else
479 hsct_info2 "Cleaning previous configuration in $PWD/helenos_build."
480 rm -rf helenos_build
481 mkdir helenos_build
482 cd helenos_build
483 hsct_info2 "Configuring for $profile."
484 "$HELENOS_ROOT"/configure.sh "$profile"
487 if [ $? -ne 0 ]; then
488 if [ -z "$profile" ]; then
489 hsct_error "Failed to reuse existing HelenOS configuration."
490 else
491 hsct_error "Failed to automatically configure HelenOS for profile '$profile'."
493 return 75
496 hsct_update
498 hsct_info "Creating facade toolchain."
499 mkdir -p facade
500 facade_path="$PWD/facade"
503 . helenos/config.sh
505 if [ -z "$HELENOS_ARCH" ]; then
506 hsct_error "HELENOS_ARCH undefined."
507 return 76
510 cd $HSCT_HOME/facade
511 for x in *; do
512 install -m 755 "$x" "$facade_path/$HELENOS_ARCH-helenos-$x"
513 done
516 if [ $? -ne 0 ]; then
517 hsct_error "Failed to create toolchain facade for profile '$profile'."
518 return 77
521 hsct_save_config
523 return 0
526 alias leave_script_ok='return 0 2>/dev/null || exit 0'
527 alias leave_script_err='return 1 2>/dev/null || exit 1'
529 hsct_print_vars() {
530 # This is separate from the rest, so that the user can run
531 # eval `path/to/hsct.sh vars` to get these vars in interactive shell.
533 hsct_load_config
534 HELENOS_EXPORT_ROOT="$HSCT_CACHE_DIR"
535 HELENOS_CONFIG="$HSCT_CACHE_DIR/config.sh"
537 if ! [ -e "$HELENOS_CONFIG" ]; then
538 hsct_error "Configuration not found. Maybe you need to run init first?"
539 return 78
542 . $HELENOS_CONFIG
544 echo "export HELENOS_EXPORT_ROOT='$HSCT_CACHE_DIR'"
545 echo "export HSCT_REAL_CC='$HELENOS_TARGET-gcc'"
546 echo "export HSCT_REAL_CXX='$HELENOS_TARGET-g++'"
548 echo "export HSCT_ARFLAGS='$HELENOS_ARFLAGS'"
549 echo "export HSCT_CPPFLAGS='-isystem $HSCT_INCLUDE_DIR $HELENOS_CPPFLAGS'"
550 echo "export HSCT_CFLAGS='$HELENOS_CFLAGS'"
551 echo "export HSCT_CXXFLAGS='$HELENOS_CXXFLAGS'"
552 echo "export HSCT_ASFLAGS='$HELENOS_ASFLAGS'"
553 echo "export HSCT_LDFLAGS='-L $HSCT_LIB_DIR $HELENOS_LDFLAGS'"
554 echo "export HSCT_LDLIBS='$HELENOS_LDLIBS'"
556 target="$HELENOS_ARCH-helenos"
557 cctarget="$HELENOS_ARCH-linux-gnu"
558 cvars="CC=$target-cc CXX=$target-cxx AR=$target-ar AS=$target-as CPP=$target-cpp NM=$target-nm OBJDUMP=$target-objdump OBJCOPY=$target-objcopy STRIP=$target-strip RANLIB=$target-ranlib"
560 echo "export HSCT_CC='$target-cc'"
561 echo "export HSCT_CXX='$target-cxx'"
562 echo "export HSCT_TARGET='$target'"
563 echo "export HSCT_REAL_TARGET='$HELENOS_TARGET'"
564 # Target to set for cross-compiled cross-compilers.
565 echo "export HSCT_CCROSS_TARGET='$cctarget'"
566 echo "export HSCT_CONFIGURE_VARS='$cvars'"
567 echo "export HSCT_CONFIGURE_ARGS='--build=`sh $HSCT_HOME/config.guess` --host=$target $cvars'"
569 echo "export HELENOS_CROSS_PATH=$HELENOS_CROSS_PATH"
570 echo "export PATH='$PWD/facade:$HELENOS_CROSS_PATH:$PATH'"
573 hsct_pkg() {
574 hsct_load_config
575 eval `hsct_print_vars`
577 if [ -z "$HELENOS_EXPORT_ROOT" ]; then
578 case "$HSCT_ACTION" in
579 clean|distclean|fetch)
582 return 79
584 esac
587 HSCT_MY_DIR="$HSCT_DIST_DIR/$HSCT_HARBOUR_NAME"
588 HSCT_OVERLAY="$HELENOS_ROOT/uspace/overlay"
589 HSCT_CONFIG_SUB="$HSCT_HOME/config.sub"
591 if ! [ "$HSCT_PARALLELISM" -ge 0 ] 2>/dev/null; then
592 HSCT_PARALLELISM="1"
595 if ! [ -d "$HSCT_HOME/$HSCT_HARBOUR_NAME" ]; then
596 hsct_error "Unknown package $HSCT_HARBOUR_NAME."
597 leave_script_err
600 if ! [ -r "$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR" ]; then
601 hsct_error "HARBOUR file missing." >&2
602 leave_script_err
605 # Source the harbour to get access to the variables and functions
606 . "$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR"
608 if [ "$shipfunnels" -ne "1" ] 2>/dev/null; then
609 shipfunnels="$HSCT_PARALLELISM"
612 case "$HSCT_ACTION" in
613 clean)
614 hsct_clean
616 distclean)
617 hsct_distclean
619 fetch)
620 hsct_fetch
622 build)
623 hsct_build
625 package)
626 hsct_package
628 install)
629 hsct_install
631 archive)
632 hsct_archive
635 hsct_error "Internal error, we shall not get to this point!"
636 leave_script_err
638 esac
640 return $?
643 HSCT_ACTION="$1"
645 case "$HSCT_ACTION" in
646 clean|distclean|fetch|build|package|install|archive)
647 shift
648 if ! hsct_process_harbour_opts "$@"; then
649 leave_script_err
651 if [ -z "$HSCT_HARBOUR_NAME" ]; then
652 hsct_usage "$0"
653 leave_script_err
655 hsct_pkg
656 exit $?
658 vars)
659 hsct_print_vars
660 exit $?
662 init)
663 hsct_init "$2" "$3" "$4"
664 exit $?
666 help|--help|-h|-?)
667 hsct_usage "$0"
668 leave_script_ok
670 update)
671 hsct_update
672 exit $?
675 hsct_usage "$0"
676 leave_script_err
678 esac