aboutsummaryrefslogtreecommitdiff
path: root/build.sh.in
diff options
context:
space:
mode:
Diffstat (limited to 'build.sh.in')
-rw-r--r--build.sh.in780
1 files changed, 780 insertions, 0 deletions
diff --git a/build.sh.in b/build.sh.in
new file mode 100644
index 0000000..43c648a
--- /dev/null
+++ b/build.sh.in
@@ -0,0 +1,780 @@
+#!/bin/sh
+
+# file : build.sh.in
+# license : MIT; see accompanying LICENSE file
+
+usage="Usage: $0 [-h|--help] [<options>] [--] <c++-compiler> [<compile-options>] [-- <link-options>]"
+
+# Package repository URL (or path).
+#
+if test -z "$BUILD2_REPO"; then
+ BUILD2_REPO="@BUILD2_REPO@"
+fi
+
+# Package versions.
+#
+build2_ver="@BUILD2_VERSION@"
+bpkg_ver="@BPKG_VERSION@"
+bdep_ver="@BDEP_VERSION@"
+
+# Standard modules comma-separated list and versions.
+#
+# NOTE: we currently print the list as a single line and will need to somehow
+# change that when it becomes too long.
+#
+standard_modules="autoconf, kconfig"
+autoconf_ver="@AUTOCONF_VERSION@"
+kconfig_ver="@KCONFIG_VERSION@"
+
+# The bpkg configuration directory.
+#
+cver="@CONFIG_VER@"
+cdir="build2-toolchain-$cver"
+
+diag ()
+{
+ echo "$*" 1>&2
+}
+
+# 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).
+#
+run ()
+{
+ diag "+ $@"
+ "$@"
+ if test "$?" -ne "0"; then
+ exit 1
+ fi
+}
+
+owd="$(pwd)"
+
+local=
+bpkg_install=true
+bdep_install=true
+modules="$standard_modules"
+system=
+private=
+idir=
+exe_prefix=
+exe_suffix=
+stage_suffix="-stage"
+jobs=
+sudo=
+trust=
+timeout=
+make=
+make_options=
+verbose=
+
+while test $# -ne 0; do
+ case "$1" in
+ -h|--help)
+ diag
+ diag "$usage"
+ diag "Options:"
+ diag " --local Don't build from packages, only from local source."
+ diag " --no-bpkg Don't install bpkg nor bdep (requires --local)."
+ diag " --no-bdep Don't install bdep."
+ diag " --no-modules Don't install standard build system modules."
+ diag " --modules <list> Install only specified standard build system modules."
+ diag " --install-dir <dir> Alternative installation directory."
+ diag " --system <list> Use system-installed versions of specified dependencies."
+ diag " --exe-prefix <pfx> Toolchain executables name prefix."
+ diag " --exe-suffix <sfx> Toolchain executables name suffix."
+ diag " --stage-suffix <sfx> Staged executables name suffix ('-stage' by default)."
+ diag " --sudo <prog> Optional sudo program to use (pass false to disable)."
+ diag " --private Install shared libraries into private subdirectory."
+ diag " --jobs|-j <num> Number of jobs to perform in parallel."
+ diag " --repo <loc> Alternative package repository location."
+ diag " --trust <fp> Repository certificate fingerprint to trust."
+ diag " --timeout <sec> Network operations timeout in seconds."
+ diag " --make <arg> Bootstrap using GNU make instead of script."
+ diag " --verbose <level> Diagnostics verbosity level between 0 and 6."
+ diag
+ diag "By default the script will install into /usr/local with private"
+ diag "library subdirectories and using sudo(1). To enable private"
+ diag "subdirectories and/or use sudo for a custom installation location,"
+ diag "you need to specify --private and/or --sudo explicitly, for example:"
+ diag
+ diag "$0 --install-dir /opt/build2 --sudo sudo g++"
+ diag
+ diag "If --jobs|-j is unspecified, then the bootstrap step is performed"
+ diag "serially with the rest of the process using the number of available"
+ diag "hardware threads."
+ diag
+ diag "The --trust option recognizes two special values: 'yes' (trust"
+ diag "everything) and 'no' (trust nothing)."
+ diag
+ diag "The --make option can be used to bootstrap using GNU make. The"
+ diag "first --make value should specify the make executable optionally"
+ diag "followed by additional make options, for example:"
+ diag
+ diag "$0 --make make --make -j8 g++"
+ diag
+ diag "If --jobs|-j is specified, then its value is passed to make before"
+ diag "any additional options."
+ diag
+ diag "If specified, <compile-options> override the default (-O3) compile"
+ diag "options (config.cc.coptions) in the bpkg configuration used to build"
+ diag "and install the final toolchain. For example, to build with the debug"
+ diag "information (and without optimization):"
+ diag
+ diag "$0 g++ -g"
+ diag
+ diag "Use --system <list> to specify a comma-separated list of dependencies"
+ diag "to use from the system rather than building them from source, for"
+ diag "example:"
+ diag
+ diag "$0 --system libsqlite3,libpkg-config g++"
+ diag
+ diag "The script by default installs the following standard build system"
+ diag "modules:"
+ diag
+ diag "$standard_modules"
+ diag
+ diag "Use --no-modules to suppress installing build system modules or"
+ diag "--modules <list> to specify a comma-separated subset to install."
+ diag
+ diag "See the BOOTSTRAP-UNIX file for details."
+ diag
+ exit 0
+ ;;
+ --local)
+ local=true
+ shift
+ ;;
+ --no-bpkg)
+ bpkg_install=
+ shift
+ ;;
+ --no-bdep)
+ bdep_install=
+ shift
+ ;;
+ --no-modules)
+ modules=
+ shift
+ ;;
+ --modules)
+ shift
+ modules="$1"
+ shift
+ ;;
+ --system)
+ shift
+ system="$1"
+ shift
+ ;;
+ --private)
+ private=config.install.private=build2
+ shift
+ ;;
+ --install-dir)
+ shift
+ if test $# -eq 0; then
+ diag "error: installation directory expected after --install-dir"
+ diag "$usage"
+ exit 1
+ fi
+ idir="$1"
+ shift
+ ;;
+ --exe-prefix)
+ shift
+ if test $# -eq 0; then
+ diag "error: executables name prefix expected after --exe-prefix"
+ diag "$usage"
+ exit 1
+ fi
+ exe_prefix="$1"
+ shift
+ ;;
+ --exe-suffix)
+ shift
+ if test $# -eq 0; then
+ diag "error: executables name suffix expected after --exe-suffix"
+ diag "$usage"
+ exit 1
+ fi
+ exe_suffix="$1"
+ shift
+ ;;
+ --stage-suffix)
+ shift
+ if test $# -eq 0; then
+ diag "error: staged executables name suffix expected after --stage-suffix"
+ diag "$usage"
+ exit 1
+ fi
+ stage_suffix="$1"
+ shift
+ ;;
+ -j|--jobs)
+ shift
+ if test $# -eq 0; then
+ diag "error: number of jobs expected after --jobs|-j"
+ diag "$usage"
+ exit 1
+ fi
+ jobs="-j $1"
+ shift
+ ;;
+ --sudo)
+ shift
+ if test $# -eq 0; then
+ diag "error: sudo program expected after --sudo"
+ diag "$usage"
+ exit 1
+ fi
+ sudo="$1"
+ shift
+ ;;
+ --repo)
+ shift
+ if test $# -eq 0; then
+ diag "error: repository location expected after --repo"
+ diag "$usage"
+ exit 1
+ fi
+ BUILD2_REPO="$1"
+ shift
+ ;;
+ --trust)
+ shift
+ if test $# -eq 0; then
+ diag "error: certificate fingerprint expected after --trust"
+ diag "$usage"
+ exit 1
+ fi
+ trust="$1"
+ shift
+ ;;
+ --timeout)
+ shift
+ if test $# -eq 0; then
+ diag "error: value in seconds expected after --timeout"
+ diag "$usage"
+ exit 1
+ fi
+ timeout="$1"
+ shift
+ ;;
+ --make)
+ shift
+ if test $# -eq 0; then
+ diag "error: argument expected after --make"
+ diag "$usage"
+ exit 1
+ fi
+ if test -z "$make"; then
+ make="$1"
+ else
+ make_options="$make_options $1"
+ fi
+ shift
+ ;;
+ --verbose)
+ shift
+ if test $# -eq 0; then
+ diag "error: diagnostics level between 0 and 6 expected after --verbose"
+ diag "$usage"
+ exit 1
+ fi
+ verbose="$1"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+# Compiler.
+#
+if test $# -eq 0; then
+ diag "error: compiler executable expected"
+ diag "$usage"
+ exit 1
+else
+ cxx="$1"
+ shift
+fi
+
+# Compile and link options.
+#
+compile_ops=
+link_ops=
+
+while test $# -ne 0; do
+ if test "$1" != "--"; then
+ compile_ops="$compile_ops $1"
+ shift
+ else
+ shift
+ break
+ fi
+done
+
+while test $# -ne 0; do
+ link_ops="$link_ops $1"
+ shift
+done
+
+if test -z "$compile_ops"; then
+ compile_ops=-O3
+fi
+
+if test -z "$link_ops"; then
+ link_ops="[null]"
+fi
+
+# Merge jobs and make_options into make.
+#
+if test -n "$make"; then
+ if test -n "$jobs"; then
+ make="$make $jobs"
+ fi
+
+ if test -n "$make_options"; then
+ make="$make$make_options" # Already has leading space.
+ fi
+fi
+
+# If --no-bpkg is specified, then we require --local to also be specified
+# since it won't be possible to build things from packages without bpkg. Also
+# imply --no-bdep in this case, since bdep is pretty much useless without
+# bpkg.
+#
+if test -z "$bpkg_install"; then
+ if test -z "$local"; then
+ diag "error: --no-bpkg can only be used for local installation"
+ diag " info: additionally specify --local"
+ exit 1
+ fi
+
+ bdep_install=
+fi
+
+module_version () # <name>
+{
+ eval "echo \$$1_ver"
+}
+
+# Convert the comma-separated modules list into a space-separated list.
+#
+module_list="$(echo "$modules" | sed 's/,/ /g')"
+
+for m in $module_list; do
+ if test -z "$(module_version "$m")"; then
+ diag "error: unknown standard build system module '$m'"
+ diag " info: available standard modules: $standard_modules"
+ exit 1
+ fi
+done
+
+# Convert the comma-separated list of system dependencies into a
+# space-separated list.
+#
+system_list="$(echo "$system" | sed 's/,/ /g')"
+
+# If any dependencies are specified to be used from the system, then specify
+# the respective config.import.*= variables for the bootstrap stage 2 command
+# and for the local or staged build configurations. If the installation is not
+# local, then also specify these dependencies as system for the bpkg-build
+# commands.
+#
+# As a special case, recognize the libpkgconf dependency as a request to force
+# build2 to use that instead of libpkg-config.
+#
+# Note that the build2 driver bootstrapped at stage 1 doesn't read .pc
+# files. Thus, for the bootstrap stage 2 command it is assumed that the
+# headers and libraries of the system dependencies can be found by the
+# compiler and linker at the standard locations. That, however, is not the
+# case for libpkgconf. Thus, if specifying libpkgconf as a system dependency
+# also specify its headers location via, for example, the CPATH environment
+# variable:
+#
+# $ CPATH=/usr/local/include/pkgconf ./build.sh --local --system libpkgconf g++
+#
+bootstrap_system_imports=
+system_imports=
+system_packages=
+
+for d in $system_list; do
+ v="$(echo "$d" | sed 's/[.+-]/_/g')" # Convert to variable name.
+
+ if test "$d" != "libpkgconf"; then
+ si="config.import.$v="
+ else
+ if test -z "$local"; then
+ diag "error: '--system libpkgconf' can only be used for local installation"
+ diag " info: additionally specify --local"
+ exit 1
+ fi
+
+ si="config.build2.libpkgconf=true"
+ fi
+
+ # For now these are the only third-party libraries that are used by the
+ # build system.
+ #
+ if test "$d" = "libpkg-config" -o "$d" = "libpkgconf"; then
+ bootstrap_system_imports="$si"
+ fi
+
+ # Suppress the 'dropping no longer used variable' warnings.
+ #
+ if test -z "$system_imports"; then
+ system_imports="config.config.persist='config.*'@unused=drop"
+ fi
+
+ system_imports="$system_imports $si"
+
+ if test -z "$local"; then
+ if test -n "$system_packages"; then
+ system_packages="$system_packages ?sys:$d"
+ else
+ system_packages="?sys:$d"
+ fi
+ fi
+done
+
+# If the installation directory is unspecified, then assume it is /usr/local.
+# Otherwise, if it is a relative path, then convert it to an absolute path,
+# unless the realpath program is not present on the system or doesn't
+# recognize any of the options we pass, in which case fail, advising to
+# specify an absolute installation directory.
+#
+if test -z "$idir"; then
+ idir=/usr/local
+ private=config.install.private=build2
+
+ # Only use default sudo for the default installation directory and only if
+ # it wasn't specified by the user.
+ #
+ if test -z "$sudo"; then
+ sudo="sudo"
+ fi
+elif test -n "$(echo "$idir" | sed -n 's#^[^/].*$#true#p')"; then
+
+ if ! command -v realpath >/dev/null 2>&1; then
+ diag "error: unable to execute realpath: command not found"
+ diag " info: specify absolute installation directory path"
+ exit 1
+ fi
+
+ # Don't resolve symlinks and allow non-existent path components.
+ #
+ if ! idir="$(realpath -s -m "$idir" 2>/dev/null)"; then
+ diag "error: realpath does not recognize -s -m"
+ diag " info: specify absolute installation directory path"
+ exit 1
+ fi
+fi
+
+if test "$sudo" = false; then
+ sudo=
+fi
+
+# Derive the to be installed executables names based on --exe-{prefix,suffix}.
+# Unless the installation is local, also derive the staged executables names
+# based on --stage-suffix and verify that they don't clash with existing
+# filesystem entries as well as the executables being installed.
+#
+b="${exe_prefix}b$exe_suffix"
+bpkg="${exe_prefix}bpkg$exe_suffix"
+bdep="${exe_prefix}bdep$exe_suffix"
+
+if test -z "$local"; then
+ b_stage="b$stage_suffix"
+ bpkg_stage="bpkg$stage_suffix"
+
+ if test -e "$idir/bin/$b_stage"; then
+ diag "error: staged executable name '$b_stage' clashes with existing $idir/bin/$b_stage"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+
+ if test -e "$idir/bin/$bpkg_stage"; then
+ diag "error: staged executable name '$bpkg_stage' clashes with existing $idir/bin/$bpkg_stage"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+
+ if test "$stage_suffix" = "$exe_suffix" -a -z "$exe_prefix"; then
+ diag "error: suffix '$exe_suffix' is used for both final and staged executables"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+fi
+
+if test -f build/config.build; then
+ diag "error: current directory already configured, start with clean source"
+ exit 1
+fi
+
+if test -z "$local" -a -d "../$cdir"; then
+ diag "error: ../$cdir/ bpkg configuration directory already exists, remove it"
+ exit 1
+fi
+
+# Add $idir/bin to PATH in case it is not already there.
+#
+PATH="$idir/bin:$PATH"
+export PATH
+
+sys="$(build2/config.guess | sed -n 's/^[^-]*-[^-]*-\(.*\)$/\1/p')"
+
+case "$sys" in
+ mingw32 | mingw64 | msys | msys2 | cygwin)
+ conf_rpath="[null]"
+ conf_rpath_stage="[null]"
+ conf_sudo="[null]"
+ ;;
+ *)
+ if test -n "$private"; then
+ conf_rpath="$idir/lib/build2"
+ else
+ conf_rpath="$idir/lib"
+ fi
+
+ conf_rpath_stage="$idir/lib"
+
+ if test -n "$sudo"; then
+ conf_sudo="$sudo"
+ else
+ conf_sudo="[null]"
+ fi
+ ;;
+esac
+
+# We don't have arrays in POSIX shell but we should be ok as long as none of
+# the configuration and option values contain spaces. Note also that the
+# expansion must be unquoted.
+#
+conf_exe_affixes=
+
+if test -n "$exe_prefix"; then
+ conf_exe_affixes="config.bin.exe.prefix=$exe_prefix"
+fi
+
+if test -n "$exe_suffix"; then
+ conf_exe_affixes="$conf_exe_affixes config.bin.exe.suffix=$exe_suffix"
+fi
+
+bpkg_fetch_ops=
+bpkg_build_ops=
+
+if test -n "$timeout"; then
+ bpkg_fetch_ops="--fetch-timeout $timeout"
+ bpkg_build_ops="--fetch-timeout $timeout"
+fi
+
+if test "$trust" = "yes"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust-yes"
+elif test "$trust" = "no"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust-no"
+elif test -n "$trust"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust $trust"
+fi
+
+if test -n "$verbose"; then
+ verbose="--verbose $verbose"
+fi
+
+# Suppress loading of default options files.
+#
+BUILD2_DEF_OPT="0"
+export BUILD2_DEF_OPT
+
+BPKG_DEF_OPT="0"
+export BPKG_DEF_OPT
+
+BDEP_DEF_OPT="0"
+export BDEP_DEF_OPT
+
+# Bootstrap, stage 1.
+#
+# Note: disable all warnings since we cannot do anything more granular during
+# bootstrap stage 1.
+#
+run cd build2
+if test -z "$make"; then
+ run ./bootstrap.sh "$cxx" -w
+else
+ run $make -f ./bootstrap.gmake "CXX=$cxx" CXXFLAGS=-w
+fi
+run build2/b-boot --version
+
+# Bootstrap, stage 2.
+#
+run build2/b-boot $verbose $jobs config.cxx="$cxx" config.bin.lib=static $bootstrap_system_imports build2/exe{b}
+mv build2/b build2/b-boot
+run build2/b-boot --version
+
+run cd ..
+
+# Local installation early return.
+#
+if test "$local" = true; then
+
+ run build2/build2/b-boot $verbose configure \
+config.config.hermetic=true \
+config.cxx="$cxx" \
+config.cc.coptions="${compile_ops# }" \
+config.cc.loptions="${link_ops# }" \
+config.bin.lib=shared \
+config.bin.rpath="$conf_rpath" \
+config.install.root="$idir" \
+config.install.sudo="$conf_sudo" \
+$conf_exe_affixes \
+$private \
+$system_imports
+
+ # Install toolchain.
+ #
+ projects="build2/"
+
+ if test "$bpkg_install" = true; then
+ projects="$projects bpkg/"
+ fi
+
+ if test "$bdep_install" = true; then
+ projects="$projects bdep/"
+ fi
+
+ run build2/build2/b-boot $verbose $jobs install: $projects
+
+ run command -v "$b"
+ run "$b" --version
+
+ if test "$bpkg_install" = true; then
+ run command -v "$bpkg"
+ run "$bpkg" --version
+ fi
+
+ if test "$bdep_install" = true; then
+ run command -v "$bdep"
+ run "$bdep" --version
+ fi
+
+ # Install modules.
+ #
+ projects=
+ tests=
+
+ for m in $module_list; do
+ projects="$projects libbuild2-$m/"
+ tests="$tests tests/libbuild2-$m-tests/"
+ done
+
+ if test -n "$projects"; then
+ run "$b" $verbose $jobs install: '!config.install.scope=project' $projects
+ run "$b" $verbose noop: $tests
+ fi
+
+ diag
+ diag "Toolchain installation: $idir/bin"
+ diag "Build configuration: $owd"
+ diag
+
+ exit 0
+fi
+
+# Build and stage the build system and the package manager.
+#
+run build2/build2/b-boot $verbose configure \
+config.cxx="$cxx" \
+config.bin.lib=shared \
+config.bin.suffix="$stage_suffix" \
+config.bin.rpath="$conf_rpath_stage" \
+config.install.root="$idir" \
+config.install.data_root=root/stage \
+config.install.sudo="$conf_sudo" \
+$system_imports
+
+run build2/build2/b-boot $verbose $jobs install: build2/ bpkg/
+
+run command -v "$b_stage"
+run "$b_stage" --version
+
+run command -v "$bpkg_stage"
+run "$bpkg_stage" --version
+
+# Build the entire toolchain from packages.
+#
+run cd ..
+run mkdir "$cdir"
+run cd "$cdir"
+cdir="$(pwd)" # Save full path for later.
+
+run "$bpkg_stage" $verbose create \
+cc \
+config.config.hermetic=true \
+config.cxx="$cxx" \
+config.cc.coptions="${compile_ops# }" \
+config.cc.loptions="${link_ops# }" \
+config.bin.lib=shared \
+config.bin.rpath="$conf_rpath" \
+config.install.root="$idir" \
+config.install.sudo="$conf_sudo" \
+$conf_exe_affixes \
+$private
+
+packages="build2/$build2_ver bpkg/$bpkg_ver"
+
+if test "$bdep_install" = true; then
+ packages="$packages bdep/$bdep_ver"
+fi
+
+run "$bpkg_stage" $verbose add "$BUILD2_REPO"
+run "$bpkg_stage" $verbose $bpkg_fetch_ops fetch
+run "$bpkg_stage" $verbose $jobs $bpkg_build_ops build --for install --yes --plan= $packages $system_packages
+run "$bpkg_stage" $verbose $jobs install --all
+
+run command -v "$b"
+run "$b" --version
+
+run command -v "$bpkg"
+run "$bpkg" --version
+
+if test "$bdep_install" = true; then
+ run command -v "$bdep"
+ run "$bdep" --version
+fi
+
+# Build, install, and verify the build system modules.
+#
+packages=
+tests=
+
+for m in $module_list; do
+ packages="$packages libbuild2-$m/$(module_version "$m")"
+ tests="$tests tests/libbuild2-$m-tests/"
+done
+
+if test -n "$packages"; then
+ run "$bpkg" $verbose $jobs $bpkg_build_ops build --for install $packages $system_packages
+ run "$bpkg" $verbose $jobs install '!config.install.scope=project' --all-pattern=libbuild2-*
+fi
+
+run cd "$owd"
+
+if test -n "$tests"; then
+ run "$b" $verbose noop: $tests
+fi
+
+# Clean up stage.
+#
+run "$b" $verbose $jobs uninstall: build2/ bpkg/
+
+diag
+diag "Toolchain installation: $idir/bin"
+diag "Build configuration: $cdir"
+diag