PCC: fix linker configuration
[harbours.git] / hsct.sh
blobf40db0e7a4bc4275dded96af650d3b300f7e0f71
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 built directory."
75 echo " fetch Fetch sources (e.g. download from homepage)."
76 echo " build Build given package."
77 echo " package Save installable files to allow cleaning."
78 echo " install Install to uspace/dist of HelenOS."
79 echo " archive Create tarball instead of installing."
80 echo " $1 init [/path/to/HelenOS] [profile]"
81 echo " Initialize current directory as coastline build directory".
82 echo " Full path has to be provided to the HelenOS source tree."
83 echo " If profile is specified, forcefully rebuild to specified profile."
84 echo " If no argument is provided, path to HelenOS source tree is"
85 echo " read from the HELENOS_ROOT environment variable."
86 echo " $1 help"
87 echo " Display this help and exit."
90 # Print high-level information message.
91 hsct_info() {
92 echo ">>>" "$@" >&2
95 # Print lower-level information message (additional info after hsct_info).
96 hsct_info2() {
97 echo " ->" "$@" >&2
100 # Print information message from HARBOUR script.
101 msg() {
102 hsct_info "$@"
105 # Print high-level error message.
106 hsct_error() {
107 echo "[hsct]:" "Error:" "$@" >&2
110 # Print additional details to the error message.
111 hsct_error2() {
112 echo "[hsct]:" " -> " "$@" >&2
115 # Run a command but print it first.
116 hsct_run_echo() {
117 echo -n "[hsct]: "
118 for ___i in "$@"; do
119 echo -n "$___i" | sed -e 's#"#\\"#g' -e 's#.*#"&" #'
120 done
121 echo
122 "$@"
125 # Run comman from HARBOUR script and print it as well.
126 run() {
127 hsct_run_echo "$@"
130 hsct_process_harbour_opts() {
131 HSCT_OPTS_NO_DEPENDENCY_BUILDING=false
132 HSCT_OPTS_NO_FILE_DOWNLOADING=false
133 HSCT_HARBOUR_NAME=""
135 while [ "$#" -ne 0 ]; do
136 case "$1" in
137 --no-deps)
138 HSCT_OPTS_NO_DEPENDENCY_BUILDING=true
140 --no-fetch)
141 HSCT_OPTS_NO_FILE_DOWNLOADING=true
143 --*)
144 hsct_error "Unknown option $1."
145 return 60
148 if [ -z "$HSCT_HARBOUR_NAME" ]; then
149 HSCT_HARBOUR_NAME="$1"
150 else
151 hsct_error "Only one package name allowed."
152 return 61
155 esac
156 shift
157 done
159 return 0
162 # Fetch all the specified files in the HARBOUR
163 hsct_fetch() {
164 mkdir -p "$HSCT_SOURCES_DIR"
165 hsct_info "Fetching sources..."
166 for _url in $shipsources; do
167 _filename=`basename "$_url"`
168 if [ "$_filename" = "$_url" ]; then
169 continue
171 if ! [ -r "$HSCT_SOURCES_DIR/$_filename" ]; then
172 if $HSCT_OPTS_NO_FILE_DOWNLOADING; then
173 hsct_error "File $_filename missing, cannot continue."
174 hsct_error2 "Build without --no-fetch."
175 return 62
178 hsct_info2 "Fetching $_filename..."
179 # Remove the file even on Ctrl-C when fetching
180 trap "rm -f \"$HSCT_SOURCES_DIR/$_filename\"; echo" SIGINT SIGQUIT
181 if ! wget $HSCT_WGET_OPTS "$_url" -O "$HSCT_SOURCES_DIR/$_filename"; then
182 rm -f "$HSCT_SOURCES_DIR/$_filename"
183 hsct_error "Failed to fetch $_url."
184 return 63
186 trap - SIGINT SIGQUIT
188 # TODO - check MD5
189 done
190 return 0
193 # Remove the build directory of given package.
194 hsct_clean() {
195 hsct_info "Cleaning build directory..."
196 rm -rf "$HSCT_BUILD_DIR/$shipname/"*
199 # Build the package.
200 hsct_build() {
201 mkdir -p "$HSCT_BUILD_DIR/$shipname"
202 if [ -e "$HSCT_BUILD_DIR/${shipname}.built" ]; then
203 hsct_info "No need to build $shipname."
204 return 0
207 # Check for prerequisities
208 for tug in $shiptugs; do
209 if ! [ -e "$HSCT_BUILD_DIR/${tug}.packaged" ]; then
210 if $HSCT_OPTS_NO_DEPENDENCY_BUILDING; then
211 hsct_error "Dependency $tug not built, cannot continue."
212 hsct_error2 "Build $tug first or run without --no-deps."
213 return 64
215 hsct_info "Need to build $tug first."
216 hsct_info2 "Running $HSCT_HSCT package $tug"
218 $HSCT_HSCT package $tug
219 exit $?
221 if [ $? -ne 0 ]; then
222 hsct_error "Failed to package dependency $tug."
223 hsct_error2 "Cannot continue building $shipname."
224 return 65
226 hsct_info2 "Back from building $tug."
228 done
230 hsct_fetch || return $?
232 for _url in $shipsources; do
233 _filename=`basename "$_url"`
234 if [ "$_filename" = "$_url" ]; then
235 _origin="$HSCT_HOME/$shipname/$_filename"
236 else
237 _origin="$HSCT_SOURCES_DIR/$_filename"
239 ln -srf "$_origin" "$HSCT_BUILD_DIR/$shipname/$_filename"
240 done
243 cd "$HSCT_BUILD_DIR/$shipname/"
244 hsct_info "Building..."
245 set -o errexit
246 build
247 exit $?
249 if [ $? -ne 0 ]; then
250 hsct_error "Build failed!"
251 return 66
253 touch "$HSCT_BUILD_DIR/${shipname}.built"
254 return 0
257 # Pseudo-installation - copy from build directory to "my" directory, copy libraries
258 hsct_package() {
259 mkdir -p "$HSCT_INCLUDE_DIR" || { hsct_error "Failed to create include directory."; return 67; }
260 mkdir -p "$HSCT_LIB_DIR" || { hsct_error "Failed to create library directory."; return 67; }
261 mkdir -p "$HSCT_MY_DIR" || { hsct_error "Failed to create package directory."; return 67; }
263 if [ -e "$HSCT_BUILD_DIR/${shipname}.packaged" ]; then
264 hsct_info "No need to package $shipname."
265 return 0;
268 hsct_build || return $?
271 cd "$HSCT_BUILD_DIR/$shipname/"
272 hsct_info "Packaging..."
273 set -o errexit
274 package
275 exit $?
277 if [ $? -ne 0 ]; then
278 hsct_error "Packaging failed!"
279 return 68
281 touch "$HSCT_BUILD_DIR/${shipname}.packaged"
282 return 0
285 # Install the package to HelenOS source tree (to uspace/overlay).
286 hsct_install() {
287 hsct_package || return $?
289 hsct_info "Installing..."
290 if ls "$HSCT_MY_DIR"/* &>/dev/null; then
291 mkdir -p "$HSCT_OVERLAY"
292 cp -v -r -L "$HSCT_MY_DIR"/* "$HSCT_OVERLAY" || return 69
293 hsct_info2 "Do not forget to rebuild the image."
294 else
295 hsct_info2 "Note: nothing to install."
297 return 0
300 # Create tarball to allow redistribution of the build packages
301 hsct_archive() {
302 hsct_package || return $?
304 hsct_info "Creating the archive..."
305 mkdir -p "$HSCT_ARCHIVE_DIR"
307 set -o errexit
308 cd "$HSCT_DIST_DIR/$shipname"
309 case "$HSCT_FORMAT" in
310 tar.gz)
311 tar czf "$HSCT_ARCHIVE_DIR/$shipname.tar.gz" .
313 tar.xz)
314 tar cJf "$HSCT_ARCHIVE_DIR/$shipname.tar.xz" .
317 hsct_info "Unknown archive_format $HSCT_FORMAT."
318 exit 71
320 esac
322 if [ $? -ne 0 ]; then
323 hsct_error "Archiving failed!"
324 return 72
327 return 0
330 hsct_load_config() {
331 # Defaults
332 HSCT_CONFIG="./config.sh"
333 HSCT_WGET_OPTS=
334 HSCT_SOURCES_DIR=`pwd`/sources
335 HSCT_FORMAT="tar.xz"
336 HSCT_PARALLELISM=`nproc`
337 HELENOS_ROOT=
339 if [ -e "$HSCT_CONFIG" ]; then
340 . $HSCT_CONFIG
344 hsct_save_config() {
345 echo "HSCT_WGET_OPTS=\"${HSCT_WGET_OPTS}\"" >> "${HSCT_CONFIG}.new"
346 echo "HSCT_SOURCES_DIR=\"${HSCT_SOURCES_DIR}\"" >> "${HSCT_CONFIG}.new"
347 echo "HSCT_FORMAT=\"${HSCT_FORMAT}\"" >> "${HSCT_CONFIG}.new"
348 echo "HSCT_PARALLELISM=\"${HSCT_PARALLELISM}\"" >> "${HSCT_CONFIG}.new"
349 echo "HELENOS_ROOT=\"${HELENOS_ROOT}\"" >> "${HSCT_CONFIG}.new"
350 mv "${HSCT_CONFIG}.new" "${HSCT_CONFIG}"
353 # Initialize current directory for coastline building.
354 hsct_init() {
355 hsct_load_config
357 _root_dir=$1
358 profile=$2
360 if [ -z "$_root_dir" ]; then
361 # Try to get HELENOS_ROOT from the environment if not specified.
362 _root_dir="$HELENOS_ROOT"
365 if [ -z "$_root_dir" ]; then
366 hsct_error "HELENOS_ROOT is not set. Either set the environment variable, or specify it on the command line.";
367 return 73
370 _root_dir=`( cd "$_root_dir"; pwd ) 2>/dev/null`
371 if ! [ -e "$_root_dir/HelenOS.config" ]; then
372 hsct_error "$_root_dir does not look like a valid HelenOS directory.";
373 return 74
376 HELENOS_ROOT="$_root_dir"
378 hsct_info "Initializing this build directory."
380 EXPORT_DIR=`pwd`/helenos
381 set -o errexit
382 cd "$HELENOS_ROOT"
383 if [ -z $profile ]; then
384 hsct_info2 "Reusing existing configuration."
385 make -j`nproc` export-posix "EXPORT_DIR=$EXPORT_DIR" HANDS_OFF=y >/dev/null 2>&1
386 else
387 hsct_info2 "Cleaning previous configuration in $PWD."
388 make distclean >/dev/null 2>&1
389 hsct_info2 "Configuring for $profile."
390 make -j`nproc` export-posix "EXPORT_DIR=$EXPORT_DIR" "PROFILE=$profile" HANDS_OFF=y >/dev/null 2>&1
393 if [ $? -ne 0 ]; then
394 hsct_error "Failed to automatically configure HelenOS for profile '$profile'."
395 return 75
398 hsct_info "Creating facade toolchain."
399 mkdir -p facade
400 facade_path="$PWD/facade"
403 . helenos/config.rc
405 if [ -z "$HELENOS_ARCH" ]; then
406 hsct_error "HELENOS_ARCH undefined."
407 return 76
410 cd $HSCT_HOME/facade
411 for x in *; do
412 install -m 755 "$x" "$facade_path/$HELENOS_ARCH-helenos-$x"
413 done
416 if [ $? -ne 0 ]; then
417 hsct_error "Failed to create toolchain facade for profile '$profile'."
418 return 77
421 hsct_save_config
423 return 0
426 alias leave_script_ok='return 0 2>/dev/null || exit 0'
427 alias leave_script_err='return 1 2>/dev/null || exit 1'
429 hsct_print_vars() {
430 # This is separate from the rest, so that the user can run
431 # eval `path/to/hsct.sh vars` to get these vars in interactive shell.
433 hsct_load_config
434 HELENOS_EXPORT_ROOT="$HSCT_CACHE_DIR"
435 HELENOS_CONFIG="$HSCT_CACHE_DIR/config.rc"
437 if ! [ -e "$HELENOS_CONFIG" ]; then
438 hsct_error "Configuration not found. Maybe you need to run init first?"
439 return 78
442 . $HELENOS_CONFIG
444 echo "export HELENOS_EXPORT_ROOT='$HSCT_CACHE_DIR'"
445 echo "export HSCT_REAL_CC='$HELENOS_TARGET-gcc'"
446 echo "export HSCT_REAL_CXX='$HELENOS_TARGET-g++'"
448 echo "export HSCT_ARFLAGS='$HELENOS_ARFLAGS'"
449 echo "export HSCT_CPPFLAGS='-isystem $HSCT_INCLUDE_DIR $HELENOS_CPPFLAGS'"
450 echo "export HSCT_CFLAGS='$HELENOS_CFLAGS'"
451 echo "export HSCT_CXXFLAGS='$HELENOS_CXXFLAGS'"
452 echo "export HSCT_ASFLAGS='$HELENOS_ASFLAGS'"
453 echo "export HSCT_LDFLAGS='-L $HSCT_LIB_DIR $HELENOS_LDFLAGS'"
454 echo "export HSCT_LDLIBS='$HELENOS_LDLIBS'"
456 target="$HELENOS_ARCH-helenos"
457 cctarget="$HELENOS_ARCH-linux-gnu"
458 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"
460 echo "export HSCT_CC='$target-cc'"
461 echo "export HSCT_CXX='$target-cxx'"
462 echo "export HSCT_TARGET='$target'"
463 echo "export HSCT_REAL_TARGET='$HELENOS_TARGET'"
464 # Target to set for cross-compiled cross-compilers.
465 echo "export HSCT_CCROSS_TARGET='$cctarget'"
466 echo "export HSCT_CONFIGURE_VARS='$cvars'"
467 echo "export HSCT_CONFIGURE_ARGS='--build=`sh $HSCT_HOME/config.guess` --host=$target $cvars'"
469 echo "export HELENOS_CROSS_PATH=$HELENOS_CROSS_PATH"
470 echo "export PATH='$PWD/facade:$HELENOS_CROSS_PATH:$PATH'"
473 hsct_pkg() {
474 hsct_load_config
475 eval `hsct_print_vars`
477 if [ -z "$HELENOS_EXPORT_ROOT" ]; then
478 case "$HSCT_ACTION" in
479 clean|fetch)
482 return 79
484 esac
487 HSCT_MY_DIR="$HSCT_DIST_DIR/$HSCT_HARBOUR_NAME"
488 HSCT_OVERLAY="$HELENOS_ROOT/uspace/overlay"
489 HSCT_CONFIG_SUB="$HSCT_HOME/config.sub"
491 if ! [ "$HSCT_PARALLELISM" -ge 0 ] 2>/dev/null; then
492 HSCT_PARALLELISM="1"
495 if ! [ -d "$HSCT_HOME/$HSCT_HARBOUR_NAME" ]; then
496 hsct_error "Unknown package $HSCT_HARBOUR_NAME."
497 leave_script_err
500 if ! [ -r "$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR" ]; then
501 hsct_error "HARBOUR file missing." >&2
502 leave_script_err
505 # Source the harbour to get access to the variables and functions
506 . "$HSCT_HOME/$HSCT_HARBOUR_NAME/HARBOUR"
508 if [ "$shipfunnels" -ne "1" ] 2>/dev/null; then
509 shipfunnels="$HSCT_PARALLELISM"
512 case "$HSCT_ACTION" in
513 clean)
514 hsct_clean
516 fetch)
517 hsct_fetch
519 build)
520 hsct_build
522 package)
523 hsct_package
525 install)
526 hsct_install
528 archive)
529 hsct_archive
532 hsct_error "Internal error, we shall not get to this point!"
533 leave_script_err
535 esac
537 return $?
540 HSCT_ACTION="$1"
542 case "$HSCT_ACTION" in
543 clean|fetch|build|package|install|archive)
544 shift
545 if ! hsct_process_harbour_opts "$@"; then
546 leave_script_err
548 if [ -z "$HSCT_HARBOUR_NAME" ]; then
549 hsct_usage "$0"
550 leave_script_err
552 hsct_pkg
553 exit $?
555 vars)
556 hsct_print_vars
557 exit $?
559 init)
560 hsct_init "$2" "$3" "$4"
561 exit $?
563 help|--help|-h|-?)
564 hsct_usage "$0"
565 leave_script_ok
568 hsct_usage "$0"
569 leave_script_err
571 esac