4 # Copyright (c) 2013-2017 Vojtech Horky
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
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
69 # Does not exit the whole script.
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."
88 echo " Display this help and exit."
91 # Print high-level information message.
96 # Print lower-level information message (additional info after hsct_info).
101 # Print information message from HARBOUR script.
106 # Print high-level error message.
108 echo "[hsct]:" "Error:" "$@" >&2
111 # Print additional details to the error message.
113 echo "[hsct]:" " -> " "$@" >&2
116 # Run a command but print it first.
120 echo -n "$___i" |
sed -e 's#"#\\"#g' -e 's#.*#"&" #'
126 # Run comman from HARBOUR script and print it as well.
131 hsct_process_harbour_opts
() {
132 HSCT_OPTS_NO_DEPENDENCY_BUILDING
=false
133 HSCT_OPTS_NO_FILE_DOWNLOADING
=false
134 HSCT_OPTS_FORCE
=false
137 while [ "$#" -ne 0 ]; do
140 HSCT_OPTS_NO_DEPENDENCY_BUILDING
=true
143 HSCT_OPTS_NO_FILE_DOWNLOADING
=true
149 hsct_error
"Unknown option $1."
153 if [ -z "$HSCT_HARBOUR_NAME" ]; then
154 HSCT_HARBOUR_NAME
="$1"
156 hsct_error
"Only one package name allowed."
167 # Fetch all the specified files in the HARBOUR
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-`
178 _filename
=`basename "$_src"`
181 echo "filename:'$_filename' url:'$_url'"
182 if [ "$_filename" = "$_url" ]; then
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."
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."
202 # Check out the specified revision
203 if [ -n "$_rev" ]; then
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."
214 if ! wget
$HSCT_WGET_OPTS "$_url" -O "$HSCT_SOURCES_DIR/$_filename"; then
215 rm -f "$HSCT_SOURCES_DIR/$_filename"
216 hsct_error
"Failed to fetch $_url."
220 trap - SIGINT SIGQUIT
227 # Remove the build directory of given package and enable rebuild
230 hsct_info
"Cleaning build directory and flag files..."
231 rm -rf "$HSCT_BUILD_DIR/$shipname"
232 rm -f "$HSCT_BUILD_DIR/${shipname}.built"
233 rm -f "$HSCT_BUILD_DIR/${shipname}.packaged"
236 # Remove the build directory of given package.
238 if [ -e "$HSCT_BUILD_DIR/${shipname}.built" ]; then
239 if ! [ -e "$HSCT_BUILD_DIR/${shipname}.packaged" ]; then
240 # Built but not packaged? If we remove the build directory
241 # we will not be able to package.
242 if ! $HSCT_OPTS_FORCE; then
243 hsct_error
"Cannot clean when built but not packaged."
244 hsct_error2
"Use distclean or --force if you know what you are doing."
249 hsct_info
"Cleaning build directory..."
250 rm -rf "$HSCT_BUILD_DIR/$shipname/"
256 mkdir
-p "$HSCT_BUILD_DIR/$shipname"
257 if [ -e "$HSCT_BUILD_DIR/${shipname}.built" ]; then
258 hsct_info
"No need to build $shipname."
262 # Check for prerequisities
263 for tug
in $shiptugs; do
264 if ! [ -e "$HSCT_BUILD_DIR/${tug}.packaged" ]; then
265 if $HSCT_OPTS_NO_DEPENDENCY_BUILDING; then
266 hsct_error
"Dependency $tug not built, cannot continue."
267 hsct_error2
"Build $tug first or run without --no-deps."
270 hsct_info
"Need to build $tug first."
271 hsct_info2
"Running $HSCT_HSCT package $tug"
273 $HSCT_HSCT package
$tug
276 if [ $?
-ne 0 ]; then
277 hsct_error
"Failed to package dependency $tug."
278 hsct_error2
"Cannot continue building $shipname."
281 hsct_info2
"Back from building $tug."
285 hsct_fetch ||
return $?
287 for _src
in $shipsources; do
288 _scheme
=`echo "$_src" | cut -d: -f 1`
289 if [ "$_scheme" = "git" ]; then
290 _filename
=`echo "$_src" | cut -d: -f 2`
291 _origin
="$HSCT_SOURCES_DIR/$_filename"
292 cp -r "$_origin" "$HSCT_BUILD_DIR/$shipname/$_filename"
295 _filename
=`basename "$_url"`
296 if [ "$_filename" = "$_url" ]; then
297 _origin
="$HSCT_HOME/$shipname/$_filename"
299 _origin
="$HSCT_SOURCES_DIR/$_filename"
302 ln -srf "$_origin" "$HSCT_BUILD_DIR/$shipname/$_filename"
307 cd "$HSCT_BUILD_DIR/$shipname/"
308 hsct_info
"Building..."
313 if [ $?
-ne 0 ]; then
314 hsct_error
"Build failed!"
317 touch "$HSCT_BUILD_DIR/${shipname}.built"
321 # Pseudo-installation - copy from build directory to "my" directory, copy libraries
323 mkdir
-p "$HSCT_INCLUDE_DIR" ||
{ hsct_error
"Failed to create include directory."; return 67; }
324 mkdir
-p "$HSCT_LIB_DIR" ||
{ hsct_error
"Failed to create library directory."; return 67; }
325 mkdir
-p "$HSCT_MY_DIR" ||
{ hsct_error
"Failed to create package directory."; return 67; }
327 if [ -e "$HSCT_BUILD_DIR/${shipname}.packaged" ]; then
328 hsct_info
"No need to package $shipname."
332 hsct_build ||
return $?
335 cd "$HSCT_BUILD_DIR/$shipname/"
336 hsct_info
"Packaging..."
341 if [ $?
-ne 0 ]; then
342 hsct_error
"Packaging failed!"
345 touch "$HSCT_BUILD_DIR/${shipname}.packaged"
349 # Install the package to HelenOS source tree (to uspace/overlay).
351 hsct_package ||
return $?
353 hsct_info
"Installing..."
354 if ls "$HSCT_MY_DIR"/* &>/dev
/null
; then
355 mkdir
-p "$HSCT_OVERLAY"
356 cp -v -r -L "$HSCT_MY_DIR"/* "$HSCT_OVERLAY" ||
return 69
357 hsct_info2
"Do not forget to rebuild the image."
359 hsct_info2
"Note: nothing to install."
364 # Create tarball to allow redistribution of the build packages
366 hsct_package ||
return $?
368 hsct_info
"Creating the archive..."
369 mkdir
-p "$HSCT_ARCHIVE_DIR"
372 cd "$HSCT_DIST_DIR/$shipname"
373 case "$HSCT_FORMAT" in
375 tar czf
"$HSCT_ARCHIVE_DIR/$shipname.tar.gz" .
378 tar cJf
"$HSCT_ARCHIVE_DIR/$shipname.tar.xz" .
381 hsct_info
"Unknown archive_format $HSCT_FORMAT."
386 if [ $?
-ne 0 ]; then
387 hsct_error
"Archiving failed!"
396 HSCT_CONFIG
="./config.sh"
398 HSCT_SOURCES_DIR
=`pwd`/sources
400 HSCT_PARALLELISM
=`nproc`
403 if [ -e "$HSCT_CONFIG" ]; then
409 echo "HSCT_WGET_OPTS=\"${HSCT_WGET_OPTS}\"" >> "${HSCT_CONFIG}.new"
410 echo "HSCT_SOURCES_DIR=\"${HSCT_SOURCES_DIR}\"" >> "${HSCT_CONFIG}.new"
411 echo "HSCT_FORMAT=\"${HSCT_FORMAT}\"" >> "${HSCT_CONFIG}.new"
412 echo "HSCT_PARALLELISM=\"${HSCT_PARALLELISM}\"" >> "${HSCT_CONFIG}.new"
413 echo "HELENOS_ROOT=\"${HELENOS_ROOT}\"" >> "${HSCT_CONFIG}.new"
414 mv "${HSCT_CONFIG}.new" "${HSCT_CONFIG}"
417 # Initialize current directory for coastline building.
424 if [ -z "$_root_dir" ]; then
425 # Try to get HELENOS_ROOT from the environment if not specified.
426 _root_dir
="$HELENOS_ROOT"
429 if [ -z "$_root_dir" ]; then
430 hsct_error
"HELENOS_ROOT is not set. Either set the environment variable, or specify it on the command line.";
434 _root_dir
=`( cd "$_root_dir"; pwd ) 2>/dev/null`
435 if ! [ -e "$_root_dir/HelenOS.config" ]; then
436 hsct_error
"$_root_dir does not look like a valid HelenOS directory.";
440 HELENOS_ROOT
="$_root_dir"
442 hsct_info
"Initializing this build directory."
444 EXPORT_DIR
=`pwd`/helenos
447 if [ -z "$profile" ]; then
448 hsct_info2
"Configuring."
449 mkdir
-p helenos_build
451 "$HELENOS_ROOT"/configure.sh
453 hsct_info2
"Cleaning previous configuration in $PWD/helenos_build."
457 hsct_info2
"Configuring for $profile."
458 "$HELENOS_ROOT"/configure.sh
"$profile"
461 hsct_info2
"Exporting data."
462 "$HELENOS_ROOT"/tools
/export.sh
"$EXPORT_DIR"
465 if [ $?
-ne 0 ]; then
466 if [ -z "$profile" ]; then
467 hsct_error
"Failed to reuse existing HelenOS configuration."
469 hsct_error
"Failed to automatically configure HelenOS for profile '$profile'."
474 hsct_info
"Creating facade toolchain."
476 facade_path
="$PWD/facade"
481 if [ -z "$HELENOS_ARCH" ]; then
482 hsct_error
"HELENOS_ARCH undefined."
488 install -m 755 "$x" "$facade_path/$HELENOS_ARCH-helenos-$x"
492 if [ $?
-ne 0 ]; then
493 hsct_error
"Failed to create toolchain facade for profile '$profile'."
502 alias leave_script_ok
='return 0 2>/dev/null || exit 0'
503 alias leave_script_err
='return 1 2>/dev/null || exit 1'
506 # This is separate from the rest, so that the user can run
507 # eval `path/to/hsct.sh vars` to get these vars in interactive shell.
510 HELENOS_EXPORT_ROOT
="$HSCT_CACHE_DIR"
511 HELENOS_CONFIG
="$HSCT_CACHE_DIR/config.sh"
513 if ! [ -e "$HELENOS_CONFIG" ]; then
514 hsct_error
"Configuration not found. Maybe you need to run init first?"
520 echo "export HELENOS_EXPORT_ROOT='$HSCT_CACHE_DIR'"
521 echo "export HSCT_REAL_CC='$HELENOS_TARGET-gcc'"
522 echo "export HSCT_REAL_CXX='$HELENOS_TARGET-g++'"
524 echo "export HSCT_ARFLAGS='$HELENOS_ARFLAGS'"
525 echo "export HSCT_CPPFLAGS='-isystem $HSCT_INCLUDE_DIR $HELENOS_CPPFLAGS'"
526 echo "export HSCT_CFLAGS='$HELENOS_CFLAGS'"
527 echo "export HSCT_CXXFLAGS='$HELENOS_CXXFLAGS'"
528 echo "export HSCT_ASFLAGS='$HELENOS_ASFLAGS'"
529 echo "export HSCT_LDFLAGS='-L $HSCT_LIB_DIR $HELENOS_LDFLAGS'"
530 echo "export HSCT_LDLIBS='$HELENOS_LDLIBS'"
532 target
="$HELENOS_ARCH-helenos"
533 cctarget
="$HELENOS_ARCH-linux-gnu"
534 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"
536 echo "export HSCT_CC='$target-cc'"
537 echo "export HSCT_CXX='$target-cxx'"
538 echo "export HSCT_TARGET='$target'"
539 echo "export HSCT_REAL_TARGET='$HELENOS_TARGET'"
540 # Target to set for cross-compiled cross-compilers.
541 echo "export HSCT_CCROSS_TARGET='$cctarget'"
542 echo "export HSCT_CONFIGURE_VARS='$cvars'"
543 echo "export HSCT_CONFIGURE_ARGS='--build=`sh $HSCT_HOME/config.guess` --host=$target $cvars'"
545 echo "export HELENOS_CROSS_PATH=$HELENOS_CROSS_PATH"
546 echo "export PATH='$PWD/facade:$HELENOS_CROSS_PATH:$PATH'"
551 eval `hsct_print_vars`
553 if [ -z "$HELENOS_EXPORT_ROOT" ]; then
554 case "$HSCT_ACTION" in
555 clean|distclean|fetch
)
563 HSCT_MY_DIR
="$HSCT_DIST_DIR/$HSCT_HARBOUR_NAME"
564 HSCT_OVERLAY
="$HELENOS_ROOT/uspace/overlay"
565 HSCT_CONFIG_SUB
="$HSCT_HOME/config.sub"
567 if ! [ "$HSCT_PARALLELISM" -ge 0 ] 2>/dev
/null
; then
571 if ! [ -d "$HSCT_HOME/$HSCT_HARBOUR_NAME" ]; then
572 hsct_error
"Unknown package $HSCT_HARBOUR_NAME."
576 if ! [ -r "$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR" ]; then
577 hsct_error
"HARBOUR file missing." >&2
581 # Source the harbour to get access to the variables and functions
582 .
"$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR"
584 if [ "$shipfunnels" -ne "1" ] 2>/dev
/null
; then
585 shipfunnels
="$HSCT_PARALLELISM"
588 case "$HSCT_ACTION" in
611 hsct_error
"Internal error, we shall not get to this point!"
621 case "$HSCT_ACTION" in
622 clean|distclean|fetch|build|package|
install|archive
)
624 if ! hsct_process_harbour_opts
"$@"; then
627 if [ -z "$HSCT_HARBOUR_NAME" ]; then
639 hsct_init
"$2" "$3" "$4"