Obsolete bootstrap.bash and ./soong wrappers

We can call directly into the blueprint bootstrap.bash using values that
soong_ui has already calculated.

Instead of calling into blueprint.bash, build minibp with microfactory,
and directly run ninja. This allows us to get individual tracing data
from each component.

Test: m -j blueprint_tools
Test: m clean; m -j blueprint_tools
Change-Id: I2239943c9a8a3ad6e1a40fa0dc914421f4b5202c
This commit is contained in:
Dan Willemsen 2017-08-04 16:04:04 -07:00
parent fd697f4256
commit 99a75cd2a5
7 changed files with 102 additions and 217 deletions

View file

@ -1,61 +1,9 @@
#!/bin/bash
set -e
echo '==== ERROR: bootstrap.bash & ./soong are obsolete ====' >&2
echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
echo '======================================================' >&2
exit 1
if [ -z "$NO_DEPRECATION_WARNING" ]; then
echo '== WARNING: bootstrap.bash & ./soong are deprecated ==' >&2
echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
echo '======================================================' >&2
fi
ORIG_SRCDIR=$(dirname "${BASH_SOURCE[0]}")
if [[ "$ORIG_SRCDIR" != "." ]]; then
if [[ ! -z "$BUILDDIR" ]]; then
echo "error: To use BUILDDIR, run from the source directory"
exit 1
fi
export BUILDDIR=$("${ORIG_SRCDIR}/build/soong/scripts/reverse_path.py" "$ORIG_SRCDIR")
cd $ORIG_SRCDIR
fi
if [[ -z "$BUILDDIR" ]]; then
echo "error: Run ${BASH_SOURCE[0]} from the build output directory"
exit 1
fi
export SRCDIR="."
export BOOTSTRAP="${SRCDIR}/bootstrap.bash"
export BLUEPRINTDIR="${SRCDIR}/build/blueprint"
export TOPNAME="Android.bp"
export RUN_TESTS="-t"
case $(uname) in
Linux)
export PREBUILTOS="linux-x86"
;;
Darwin)
export PREBUILTOS="darwin-x86"
;;
*) echo "unknown OS:" $(uname) && exit 1;;
esac
export GOROOT="${SRCDIR}/prebuilts/go/$PREBUILTOS"
if [[ $# -eq 0 ]]; then
mkdir -p $BUILDDIR
if [[ $(find $BUILDDIR -maxdepth 1 -name Android.bp) ]]; then
echo "FAILED: The build directory must not be a source directory"
exit 1
fi
export SRCDIR_FROM_BUILDDIR=$(build/soong/scripts/reverse_path.py "$BUILDDIR")
sed -e "s|@@BuildDir@@|${BUILDDIR}|" \
-e "s|@@SrcDirFromBuildDir@@|${SRCDIR_FROM_BUILDDIR}|" \
-e "s|@@PrebuiltOS@@|${PREBUILTOS}|" \
"$SRCDIR/build/soong/soong.bootstrap.in" > $BUILDDIR/.soong.bootstrap
ln -sf "${SRCDIR_FROM_BUILDDIR}/build/soong/soong.bash" $BUILDDIR/soong
fi
"$SRCDIR/build/blueprint/bootstrap.bash" "$@"

View file

@ -1,40 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import sys
# Find the best reverse path to reference the current directory from another
# directory. We use this to find relative paths to and from the source and build
# directories.
#
# If the directory is given as an absolute path, return an absolute path to the
# current directory.
#
# If there's a symlink involved, and the same relative path would not work if
# the symlink was replace with a regular directory, then return an absolute
# path. This handles paths like out -> /mnt/ssd/out
#
# For symlinks that can use the same relative path (out -> out.1), just return
# the relative path. That way out.1 can be renamed as long as the symlink is
# updated.
#
# For everything else, just return the relative path. That allows the source and
# output directories to be moved as long as they stay in the same position
# relative to each other.
def reverse_path(path):
if path.startswith("/"):
return os.path.abspath('.')
realpath = os.path.relpath(os.path.realpath('.'), os.path.realpath(path))
relpath = os.path.relpath('.', path)
if realpath != relpath:
return os.path.abspath('.')
return relpath
if __name__ == '__main__':
print(reverse_path(sys.argv[1]))

View file

@ -1,47 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import os
import shutil
import tempfile
import unittest
from reverse_path import reverse_path
class TestReversePath(unittest.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
os.chdir(self.tmpdir)
def tearDown(self):
shutil.rmtree(self.tmpdir)
def test_absolute(self):
self.assertEqual(self.tmpdir, reverse_path('/out'))
def test_relative(self):
os.mkdir('a')
os.mkdir('b')
self.assertEqual('..', reverse_path('a'))
os.chdir('a')
self.assertEqual('a', reverse_path('..'))
self.assertEqual('.', reverse_path('../a'))
self.assertEqual('../a', reverse_path('../b'))
def test_symlink(self):
os.mkdir('b')
os.symlink('b', 'a')
os.mkdir('b/d')
os.symlink('b/d', 'c')
self.assertEqual('..', reverse_path('a'))
self.assertEqual('..', reverse_path('b'))
self.assertEqual(self.tmpdir, reverse_path('c'))
self.assertEqual('../..', reverse_path('b/d'))
if __name__ == '__main__':
unittest.main()

View file

@ -1,48 +1,8 @@
#!/bin/bash
set -e
# Switch to the build directory
cd $(dirname "${BASH_SOURCE[0]}")
if [ -z "$NO_DEPRECATION_WARNING" ]; then
echo '== WARNING: bootstrap.bash & ./soong are deprecated ==' >&2
echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
echo '======================================================' >&2
fi
# The source directory path and operating system will get written to
# .soong.bootstrap by the bootstrap script.
BOOTSTRAP=".soong.bootstrap"
if [ ! -f "${BOOTSTRAP}" ]; then
echo "Error: soong script must be located in a directory created by bootstrap.bash"
exit 1
fi
source "${BOOTSTRAP}"
# Now switch to the source directory so that all the relative paths from
# $BOOTSTRAP are correct
cd ${SRCDIR_FROM_BUILDDIR}
# Ninja can't depend on environment variables, so do a manual comparison
# of the relevant environment variables from the last build using the
# soong_env tool and trigger a build manifest regeneration if necessary
ENVFILE="${BUILDDIR}/.soong.environment"
ENVTOOL="${BUILDDIR}/.bootstrap/bin/soong_env"
if [ -f "${ENVFILE}" ]; then
if [ -x "${ENVTOOL}" ]; then
if ! "${ENVTOOL}" "${ENVFILE}"; then
echo "forcing build manifest regeneration"
rm -f "${ENVFILE}"
fi
else
echo "Missing soong_env tool, forcing build manifest regeneration"
rm -f "${ENVFILE}"
fi
fi
BUILDDIR="${BUILDDIR}" NINJA="prebuilts/build-tools/${PREBUILTOS}/bin/ninja" build/blueprint/blueprint.bash "$@"
echo '==== ERROR: bootstrap.bash & ./soong are obsolete ====' >&2
echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
echo 'Without envsetup.sh, use:' >&2
echo ' build/soong/soong_ui.bash --make-mode --skip-make' >&2
echo '======================================================' >&2
exit 1

View file

@ -20,6 +20,7 @@ bootstrap_go_package {
"soong-ui-tracer",
"soong-shared",
"soong-finder",
"blueprint-microfactory",
],
srcs: [
"build.go",

View file

@ -156,7 +156,6 @@ func Build(ctx Context, config Config, what int) {
if what&BuildSoong != 0 {
// Run Soong
runSoongBootstrap(ctx, config)
runSoong(ctx, config)
}

View file

@ -15,37 +15,101 @@
package build
import (
"os"
"path/filepath"
"strconv"
"time"
"github.com/google/blueprint/microfactory"
)
func runSoongBootstrap(ctx Context, config Config) {
ctx.BeginTrace("bootstrap soong")
defer ctx.EndTrace()
cmd := Command(ctx, config, "soong bootstrap", "./bootstrap.bash")
cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
cmd.Environment.Set("NINJA_BUILDDIR", config.OutDir())
cmd.Environment.Set("NO_DEPRECATION_WARNING", "true")
cmd.Sandbox = soongSandbox
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
cmd.RunOrFatal()
}
func runSoong(ctx Context, config Config) {
ctx.BeginTrace("soong")
defer ctx.EndTrace()
cmd := Command(ctx, config, "soong",
filepath.Join(config.SoongOutDir(), "soong"), "-w", "dupbuild=err")
if config.IsVerbose() {
cmd.Args = append(cmd.Args, "-v")
func() {
ctx.BeginTrace("blueprint bootstrap")
defer ctx.EndTrace()
cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", "-t")
cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
cmd.Environment.Set("GOROOT", filepath.Join("./prebuilts/go", config.HostPrebuiltTag()))
cmd.Environment.Set("NINJA_BUILDDIR", config.OutDir())
cmd.Environment.Set("SRCDIR", ".")
cmd.Environment.Set("TOPNAME", "Android.bp")
cmd.Sandbox = soongSandbox
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
cmd.RunOrFatal()
}()
func() {
ctx.BeginTrace("environment check")
defer ctx.EndTrace()
envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
envTool := filepath.Join(config.SoongOutDir(), ".bootstrap/bin/soong_env")
if _, err := os.Stat(envFile); err == nil {
if _, err := os.Stat(envTool); err == nil {
cmd := Command(ctx, config, "soong_env", envTool, envFile)
cmd.Sandbox = soongSandbox
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
if err := cmd.Run(); err != nil {
ctx.Verboseln("soong_env failed, forcing manifest regeneration")
os.Remove(envFile)
}
} else {
ctx.Verboseln("Missing soong_env tool, forcing manifest regeneration")
os.Remove(envFile)
}
} else if !os.IsNotExist(err) {
ctx.Fatalf("Failed to stat %f: %v", envFile, err)
}
}()
func() {
ctx.BeginTrace("minibp")
defer ctx.EndTrace()
var cfg microfactory.Config
cfg.Map("github.com/google/blueprint", "build/blueprint")
if absPath, err := filepath.Abs("."); err == nil {
cfg.TrimPath = absPath
}
minibp := filepath.Join(config.SoongOutDir(), ".minibootstrap/minibp")
if _, err := microfactory.Build(&cfg, minibp, "github.com/google/blueprint/bootstrap/minibp"); err != nil {
ctx.Fatalln("Failed to build minibp:", err)
}
}()
ninja := func(name, file string) {
ctx.BeginTrace(name)
defer ctx.EndTrace()
cmd := Command(ctx, config, "soong "+name,
config.PrebuiltBuildTool("ninja"),
"-d", "keepdepfile",
"-w", "dupbuild=err",
"-j", strconv.Itoa(config.Parallel()),
"-f", filepath.Join(config.SoongOutDir(), file))
if config.IsVerbose() {
cmd.Args = append(cmd.Args, "-v")
}
cmd.Environment.Set("GOROOT", filepath.Join("./prebuilts/go", config.HostPrebuiltTag()))
cmd.Sandbox = soongSandbox
cmd.Stdin = ctx.Stdin()
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
defer ctx.ImportNinjaLog(filepath.Join(config.OutDir(), ".ninja_log"), time.Now())
cmd.RunOrFatal()
}
cmd.Environment.Set("SKIP_NINJA", "true")
cmd.Environment.Set("NO_DEPRECATION_WARNING", "true")
cmd.Sandbox = soongSandbox
cmd.Stdin = ctx.Stdin()
cmd.Stdout = ctx.Stdout()
cmd.Stderr = ctx.Stderr()
cmd.RunOrFatal()
ninja("minibootstrap", ".minibootstrap/build.ninja")
ninja("bootstrap", ".bootstrap/build.ninja")
}