summaryrefslogtreecommitdiff
path: root/upgrade
diff options
context:
space:
mode:
Diffstat (limited to 'upgrade')
-rwxr-xr-xupgrade179
1 files changed, 122 insertions, 57 deletions
diff --git a/upgrade b/upgrade
index 4ccb9aa..c98e9d6 100755
--- a/upgrade
+++ b/upgrade
@@ -1,37 +1,52 @@
#! /usr/bin/env bash
-# Upgrade remote packages in a bdep-managed build2 toolchain build,
-# essentially as if by executing:
+# Upgrade remote packages in a bdep-managed build2 toolchain build (default
+# configurations), essentially as if by executing:
#
# bdep sync -fur && b
#
# In each project of the toolchain.
#
# Note that we can't just do that because as soon as we drop some dependency
-# package, the tools (b, bppg, etc) become non-runnable (missing shared
-# libraries, etc).
+# package, the tools (b, bpkg, etc) become non-runnable (missing shared
+# libraries, etc). The script expects the current build of the toolchain
+# to be runnable.
#
-# Note also that this script expects the build system (build2) and the rest of
-# the toolchain (bpkg, bdep, etc) to be built in separate build configuration
-# (for example, tsan for build2 and asan for the rest).
+# This script only upgrades the default configurations (including -libs, if
+# present). To upgrade the rest you can use the normal way, for example:
#
-# Finally, this script only upgrades the default configurations. To upgrade
-# the rest you can use the normal way, for example:
+# bdep sync -Fur @<cfg>|-a
#
-# bdep sync -fura
-#
-# If the -c option is specified, then the second configuration is upgraded
-# and configured but is not updated. This can be done at a later stage by
+# If the -c option is specified, the configuration is upgraded and configured
+# but only the build system is updated. This can be done at a later stage by
# running the build system in the configuration directory:
#
-# BDEP_SYNC=0 b
+# BDEP_SYNC=0 b builds/gcc7/
#
-trap "exit 1" ERR
+owd="$(pwd)"
+trap "{ cd '$owd'; exit 1; }" ERR
set -o errtrace # Trap in functions.
function info () { echo "$*" 1>&2; }
function error () { info "$*"; exit 1; }
+# Run a command with tracing (similar to set -x).
+#
+# Note that this function will execute a command with arguments that contain
+# spaces but it will not print them as quoted (and neither does set -x).
+#
+function run ()
+{
+ echo "+ $@" 1>&2
+ "$@"
+}
+
+function run_no_sync ()
+{
+ echo "+ BDEP_SYNC=0 $@" 1>&2
+ BDEP_SYNC=0 "$@"
+}
+
# Make sure the build2 tools are runnable.
#
b --version >/dev/null
@@ -54,82 +69,132 @@ done
# Get the configuration directories.
#
-bcfg="$(b info: build2/ | sed -n -re 's/^out_root: (.+)$/\1/p')"
-pcfg="$(b info: bpkg/ | sed -n -re 's/^out_root: (.+)$/\1/p')"
+tcfg="$(b info: build2/ | sed -n -re 's/^out_root: (.+)$/\1/p')"
+lcfg="$(b info: libbutl/ | sed -n -re 's/^out_root: (.+)$/\1/p')"
-if [ -z "$bcfg" -o -z "$pcfg" ]; then
+if [ -z "$tcfg" -o -z "$lcfg" ]; then
error "unable to determine build configuration directories"
fi
-bcfg="$(dirname "$bcfg")"
-pcfg="$(dirname "$pcfg")"
+tcfg="$(dirname "$tcfg")"
+lcfg="$(dirname "$lcfg")"
-if [ "$bcfg" = "$pcfg" ]; then
- error "build2 and bpkg build configuration directories are the same"
+if [ "$tcfg" = "$lcfg" ]; then
+ lcfg=
fi
# The plan is as follows:
#
-# 0. First, make backup copies of both configurations. If something goes wrong,
+# 0. First, make backup copies of configurations. If something goes wrong,
# it's likely the tools will be left in a non-runnable state.
#
-# 1. Next, install the build system on the side and then upgrade the build
-# system configuration using that plus the existing bpkg/bdep.
-#
-# 2. Finally, upgrade the rest. Note that we only have one shot at this since
-# we are running bpkg that is being upgraded.
-#
+# 1. Next, setup the environment (PATH, LD_LIBRARY_PATH) so that we use the
+# toolchain from the backup copy. Then upgrade the configurations using
+# that.
# Step 0.
#
-if test -e "$bcfg.bak"; then
- error "$bcfg.bak already exist"
+if test -e "$tcfg.bak"; then
+ error "$tcfg.bak already exist"
fi
-if test -e "$pcfg.bak"; then
- error "$pcfg.bak already exist"
+if [ -n "$lcfg" ]; then
+ if test -e "$lcfg.bak"; then
+ error "$lcfg.bak already exist"
+ fi
fi
-set -x
+run cp -rp "$tcfg" "$tcfg.bak"
-cp -rp "$bcfg" "$bcfg.bak"
-cp -rp "$pcfg" "$pcfg.bak"
+if [ -n "$lcfg" ]; then
+ run cp -rp "$lcfg" "$lcfg.bak"
+fi
# Step 1.
#
+# The main problem with running the toolchain from the backup location is the
+# rpaths embedded into the executables. We can make sure the libraries are
+# found in the backup location with LD_LIBRARY_PATH (or equivalent). But for
+# good measure let's also remove all the libraries from the original location
+# to make they don't interfere.
+#
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ so=dylib
+else
+ so=so
+fi
-BDEP_SYNC=0 b "$bcfg"/libbutl/libbutl/hxx{version}
-BDEP_SYNC=0 b "$bcfg"/build2/libbuild2/hxx{version}
+libs=()
+for f in $(find "$tcfg" -name "*.$so" -a '(' -type f -o -type l ')'); do
+ libs+=("$f")
+done
-BDEP_SYNC=0 bpkg install -d "$bcfg" \
- config.install.root=/tmp/build2-install \
- config.bin.rpath=/tmp/build2-install/lib \
- build2
+run rm -rf "${libs[@]}"
-/tmp/build2-install/bin/b --version >/dev/null
+declare -A lib_dirs
+for f in $(find "$tcfg.bak" -name "*.$so" -a '(' -type f -o -type l ')'); do
+ lib_dirs["$(dirname "$f")"]=
+done
-bpkg fetch -d "$bcfg"
-BDEP_SYNC=0 bpkg build -d "$bcfg" --build /tmp/build2-install/bin/b --keep-out -ur
+# Note that the order should not matter.
+#
+ldpath=
+for d in "${!lib_dirs[@]}"; do
+ ldpath="$d:$ldpath"
+done
-b --version >/dev/null
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ oldpath="$DYLD_LIBRARY_PATH"
+ run export DYLD_LIBRARY_PATH="$ldpath$DYLD_LIBRARY_PATH"
+else
+ oldpath="$LD_LIBRARY_PATH"
+ run export LD_LIBRARY_PATH="$ldpath$LD_LIBRARY_PATH"
+fi
+opath="$PATH"
+run export PATH="$tcfg.bak/build2/build2:$tcfg.bak/bpkg/bpkg:$tcfg.bak/bdep/bdep:$PATH"
-b build2/ # Should be a noop.
+# Make sure the backup toolchain is runnable.
+#
+run which b bpkg bdep
+run b --version >/dev/null
+run bpkg --version >/dev/null
+run bdep --version >/dev/null
-rm -rf /tmp/build2-install
+# Upgrade.
+#
+run bpkg fetch -d "$tcfg"
+run_no_sync bpkg build -d "$tcfg" --keep-out -ur $configure_only
-# Step 2.
+# In configure-only we update the build system manually.
#
-bpkg fetch -d "$pcfg"
-BDEP_SYNC=0 bpkg build -d "$pcfg" --keep-out -ur $configure_only
+if [ -n "$configure_only" ]; then
+ run_no_sync b build2/
+fi
-if [ -z "$configure_only" ]; then
+if [ -n "$lcfg" ]; then
+ run bpkg fetch -d "$lcfg"
+ run_no_sync bpkg build -d "$lcfg" --keep-out -ur $configure_only
+fi
- bpkg --version >/dev/null
- bdep --version >/dev/null
+# Restore the original environment.
+#
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ run export DYLD_LIBRARY_PATH="$oldpath"
+else
+ run export LD_LIBRARY_PATH="$oldpath"
+fi
+run export PATH="$opath"
- b bpkg/ bdep/ # Should be a noop.
+run b --version >/dev/null
+if [ -z "$configure_only" ]; then
+ run bpkg --version >/dev/null
+ run bdep --version >/dev/null
+ run b build2/ bpkg/ bdep/ # Should be a noop.
fi
-rm -rf "$bcfg.bak"
-rm -rf "$pcfg.bak"
+run rm -rf "$tcfg.bak"
+
+if [ -n "$lcfg" ]; then
+ run rm -rf "$lcfg.bak"
+fi