From 87b17d1ff46ab86ab897c50435c423f28be4895f Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Tue, 14 Jul 2015 00:39:06 -0700 Subject: [PATCH] Use SRCDIR as a working directory The existing behavior of using the build directory as the working directory is useful if you want to move/copy the output directory around and SRCDIR still refers the the source. But, it's more useful to have the source directory be the working directory. Tools like cpp(__FILE__) and other debug prints embed relative paths from the working directory. We also have tools that expect the working directory to be $TOP. Change-Id: Ia0f1d3c6b7df72d61cf5628efa2baa98bd19775b --- bootstrap.bash | 51 ++++++++++++++++++++++++++++++++--------- build.ninja.in | 2 +- cc/arm64_device.go | 2 +- cc/arm_device.go | 2 +- cc/builder.go | 10 ++++---- cc/cc.go | 4 ++-- cmd/soong_build/main.go | 4 ++-- common/config.go | 34 ++++++++++++++++++--------- common/env.go | 4 +++- soong.bash | 21 ++++++++--------- soong.bootstrap.in | 3 ++- 11 files changed, 90 insertions(+), 47 deletions(-) diff --git a/bootstrap.bash b/bootstrap.bash index f6056d653..c4c7e35c1 100755 --- a/bootstrap.bash +++ b/bootstrap.bash @@ -1,7 +1,27 @@ #!/bin/bash -export BOOTSTRAP="${BASH_SOURCE[0]}" -export SRCDIR=$(dirname "${BASH_SOURCE[0]}") +set -e + +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 + if [[ ${ORIG_SRCDIR:0:1} == '/' ]]; then + export BUILDDIR=$PWD + else + export BUILDDIR=$(python -c "import os; print os.path.relpath('.', '$ORIG_SRCDIR')") + fi + 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 TOPNAME="Android.bp" export BOOTSTRAP_MANIFEST="${SRCDIR}/build/soong/build.ninja.in" export RUN_TESTS="-t" @@ -21,16 +41,25 @@ export GOROOT="${SRCDIR}/prebuilts/go/$PREBUILTOS/" export GOARCH="amd64" export GOCHAR="6" -if [[ $(find . -maxdepth 1 -name $(basename "${BOOTSTRAP}")) ]]; then - echo "FAILED: Tried to run "$(basename "${BOOTSTRAP}")" from "$(pwd)"" - exit 1 -fi - if [[ $# -eq 0 ]]; then - sed -e "s|@@SrcDir@@|${SRCDIR}|" \ + 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 + + if [[ ${BUILDDIR:0:1} == '/' ]]; then + export SRCDIR_FROM_BUILDDIR=$PWD + else + export SRCDIR_FROM_BUILDDIR=$(python -c "import os; print os.path.relpath('.', '$BUILDDIR')") + fi + + sed -e "s|@@BuildDir@@|${BUILDDIR}|" \ + -e "s|@@SrcDirFromBuildDir@@|${SRCDIR_FROM_BUILDDIR}|" \ -e "s|@@PrebuiltOS@@|${PREBUILTOS}|" \ - "${SRCDIR}/build/soong/soong.bootstrap.in" > .soong.bootstrap - ln -sf "${SRCDIR}/build/soong/soong.bash" soong + "$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" "$@" +"$SRCDIR/build/blueprint/bootstrap.bash" "$@" diff --git a/build.ninja.in b/build.ninja.in index cf585f566..d46df7030 100644 --- a/build.ninja.in +++ b/build.ninja.in @@ -32,7 +32,7 @@ g.bootstrap.srcDir = @@SrcDir@@ builddir = ${g.bootstrap.buildDir}/.minibootstrap rule g.bootstrap.bootstrap - command = ${g.bootstrap.bootstrapCmd} -i ${in} -b ${g.bootstrap.buildDir} + command = BUILDDIR=${g.bootstrap.buildDir} ${g.bootstrap.bootstrapCmd} -i ${in} description = bootstrap ${in} generator = true diff --git a/cc/arm64_device.go b/cc/arm64_device.go index 887e1a4ca..b818ce423 100644 --- a/cc/arm64_device.go +++ b/cc/arm64_device.go @@ -61,7 +61,7 @@ func init() { pctx.StaticVariable("arm64GccVersion", "4.9") pctx.StaticVariable("arm64GccRoot", - "${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}") + "prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}") pctx.StaticVariable("arm64GccTriple", "aarch64-linux-android") diff --git a/cc/arm_device.go b/cc/arm_device.go index 58553b2bd..15f09135c 100644 --- a/cc/arm_device.go +++ b/cc/arm_device.go @@ -135,7 +135,7 @@ func init() { pctx.StaticVariable("armGccVersion", "4.9") pctx.StaticVariable("armGccRoot", - "${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}") + "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}") pctx.StaticVariable("armGccTriple", "arm-linux-androideabi") diff --git a/cc/builder.go b/cc/builder.go index d6d1a02c7..9c9bddd82 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -140,12 +140,14 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil for i, srcFile := range srcFiles { var objFile string - if strings.HasPrefix(srcFile, srcRoot) { - objFile = strings.TrimPrefix(srcFile, srcRoot) - objFile = filepath.Join(objDir, objFile) - } else if strings.HasPrefix(srcFile, intermediatesRoot) { + if strings.HasPrefix(srcFile, intermediatesRoot) { objFile = strings.TrimPrefix(srcFile, intermediatesRoot) objFile = filepath.Join(objDir, "gen", objFile) + } else if strings.HasPrefix(srcFile, srcRoot) { + srcFile, _ = filepath.Rel(srcRoot, srcFile) + objFile = filepath.Join(objDir, srcFile) + } else if srcRoot == "." && srcFile[0] != '/' { + objFile = filepath.Join(objDir, srcFile) } else { ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot) continue diff --git a/cc/cc.go b/cc/cc.go index 398a06563..34a1a56e2 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -64,8 +64,8 @@ var ( HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", common.Config.PrebuiltOS) SrcDir = pctx.VariableConfigMethod("SrcDir", common.Config.SrcDir) - LibcRoot = pctx.StaticVariable("LibcRoot", "${SrcDir}/bionic/libc") - LibmRoot = pctx.StaticVariable("LibmRoot", "${SrcDir}/bionic/libm") + LibcRoot = pctx.StaticVariable("LibcRoot", "bionic/libc") + LibmRoot = pctx.StaticVariable("LibmRoot", "bionic/libm") ) // Flags used by lots of devices. Putting them in package static variables will save bytes in diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 65194020a..254f92252 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -35,7 +35,7 @@ func main() { ctx := soong.NewContext() - configuration, err := common.NewConfig(srcDir) + configuration, err := common.NewConfig(srcDir, bootstrap.BuildDir) if err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) @@ -44,5 +44,5 @@ func main() { // Temporary hack //ctx.SetIgnoreUnknownModuleTypes(true) - bootstrap.Main(ctx, configuration, common.ConfigFileName, common.ProductVariablesFileName) + bootstrap.Main(ctx, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName) } diff --git a/common/config.go b/common/config.go index f8231f073..a7675b979 100644 --- a/common/config.go +++ b/common/config.go @@ -24,8 +24,8 @@ import ( ) // The configuration file name -const ConfigFileName = "soong.config" -const ProductVariablesFileName = "soong.variables" +const configFileName = "soong.config" +const productVariablesFileName = "soong.variables" // A FileConfigurableOptions contains options which can be configured by the // config file. These will be included in the config struct. @@ -46,7 +46,11 @@ type config struct { FileConfigurableOptions ProductVariables productVariables - srcDir string // the path of the root source directory + ConfigFileName string + ProductVariablesFileName string + + srcDir string // the path of the root source directory + buildDir string // the path of the build output directory envLock sync.Mutex envDeps map[string]string @@ -58,12 +62,12 @@ type jsonConfigurable interface { } func loadConfig(config *config) error { - err := loadFromConfigFile(&config.FileConfigurableOptions, ConfigFileName) + err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName) if err != nil { return err } - return loadFromConfigFile(&config.ProductVariables, ProductVariablesFileName) + return loadFromConfigFile(&config.ProductVariables, config.ProductVariablesFileName) } // loads configuration options from a JSON file in the cwd. @@ -120,12 +124,16 @@ func saveToConfigFile(config jsonConfigurable, filename string) error { // New creates a new Config object. The srcDir argument specifies the path to // the root source directory. It also loads the config file, if found. -func NewConfig(srcDir string) (Config, error) { +func NewConfig(srcDir, buildDir string) (Config, error) { // Make a config with default options config := Config{ config: &config{ - srcDir: srcDir, - envDeps: make(map[string]string), + ConfigFileName: filepath.Join(buildDir, configFileName), + ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName), + + srcDir: srcDir, + buildDir: buildDir, + envDeps: make(map[string]string), }, } @@ -142,8 +150,12 @@ func (c *config) SrcDir() string { return c.srcDir } +func (c *config) BuildDir() string { + return c.buildDir +} + func (c *config) IntermediatesDir() string { - return ".intermediates" + return filepath.Join(c.BuildDir(), ".intermediates") } // PrebuiltOS returns the name of the host OS used in prebuilts directories @@ -204,12 +216,12 @@ func (c *config) DeviceName() string { // DeviceOut returns the path to out directory for device targets func (c *config) DeviceOut() string { - return filepath.Join("target/product", c.DeviceName()) + return filepath.Join(c.BuildDir(), "target/product", c.DeviceName()) } // HostOut returns the path to out directory for host targets func (c *config) HostOut() string { - return filepath.Join("host", c.PrebuiltOS()) + return filepath.Join(c.BuildDir(), "host", c.PrebuiltOS()) } // HostBin returns the path to bin directory for host targets diff --git a/common/env.go b/common/env.go index 3214baa8f..8694c28aa 100644 --- a/common/env.go +++ b/common/env.go @@ -15,6 +15,8 @@ package common import ( + "path/filepath" + "android/soong" "android/soong/env" @@ -41,7 +43,7 @@ type envSingleton struct{} func (c *envSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { envDeps := ctx.Config().(Config).EnvDeps() - envFile := ".soong.environment" + envFile := filepath.Join(ctx.Config().(Config).BuildDir(), ".soong.environment") err := env.WriteEnvFile(envFile, envDeps) if err != nil { diff --git a/soong.bash b/soong.bash index 778f5e0a3..782b0b76e 100755 --- a/soong.bash +++ b/soong.bash @@ -1,13 +1,14 @@ #!/bin/bash -# Determine the build directory location based on the location of this script. -BPBUILD="${BASH_SOURCE[0]}" -BUILDDIR=`dirname "${BASH_SOURCE[0]}"` -BOOTSTRAP="${BUILDDIR}/.soong.bootstrap" +set -e + +# Switch to the build directory +cd $(dirname "${BASH_SOURCE[0]}") # 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 @@ -15,13 +16,9 @@ fi source "${BOOTSTRAP}" -if [[ ${SRCDIR_IN:0:1} == '/' ]]; then - # SRCDIR_IN is an absolute path - SRCDIR="${SRCDIR_IN}" -else - # SRCDIR_IN is a relative path - SRCDIR="${BUILDDIR}/${SRCDIR_IN}" -fi +# Now switch to the source directory so that all the relative paths from +# $BOOTSTRAP are correct +cd ${SRCDIR_FROM_BUILDDIR} # Let Blueprint know that the Ninja we're using performs multiple passes that # can regenerate the build manifest. @@ -44,4 +41,4 @@ if [ -f "${ENVFILE}" ]; then fi fi -"${SRCDIR}/prebuilts/ninja/${PREBUILTOS}/ninja" -C "${BUILDDIR}" "$@" +"prebuilts/ninja/${PREBUILTOS}/ninja" -f "${BUILDDIR}/build.ninja" "$@" diff --git a/soong.bootstrap.in b/soong.bootstrap.in index 79e4a655d..be71d15c5 100644 --- a/soong.bootstrap.in +++ b/soong.bootstrap.in @@ -1,2 +1,3 @@ -SRCDIR_IN="@@SrcDir@@" +BUILDDIR="@@BuildDir@@" +SRCDIR_FROM_BUILDDIR="@@SrcDirFromBuildDir@@" PREBUILTOS="@@PrebuiltOS@@"