Revert "Revert "Test for dangling rules in make checkbuild""
This reverts commit fb941913a3
.
Reapplies I4933187e8b72f2ef0c32d18ffea756e2c6fa417c with fixes
to disable the check for mac builds, where many modules are
disabled and the check is just going to cause more problems.
Test: m checkbuild
Change-Id: If6712c90ececd5d015fcdcdeefe0c3d4f5590711
This commit is contained in:
parent
b06ad36c1f
commit
37193495cf
|
@ -114,7 +114,11 @@ func main() {
|
||||||
} else if os.Args[1] == "--dumpvars-mode" {
|
} else if os.Args[1] == "--dumpvars-mode" {
|
||||||
dumpVars(buildCtx, config, os.Args[2:])
|
dumpVars(buildCtx, config, os.Args[2:])
|
||||||
} else {
|
} else {
|
||||||
build.Build(buildCtx, config, build.BuildAll)
|
toBuild := build.BuildAll
|
||||||
|
if config.Checkbuild() {
|
||||||
|
toBuild |= build.RunBuildTests
|
||||||
|
}
|
||||||
|
build.Build(buildCtx, config, toBuild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ bootstrap_go_package {
|
||||||
"proc_sync.go",
|
"proc_sync.go",
|
||||||
"signal.go",
|
"signal.go",
|
||||||
"soong.go",
|
"soong.go",
|
||||||
|
"test_build.go",
|
||||||
"util.go",
|
"util.go",
|
||||||
],
|
],
|
||||||
testSrcs: [
|
testSrcs: [
|
||||||
|
|
|
@ -68,6 +68,7 @@ const (
|
||||||
BuildSoong = 1 << iota
|
BuildSoong = 1 << iota
|
||||||
BuildKati = 1 << iota
|
BuildKati = 1 << iota
|
||||||
BuildNinja = 1 << iota
|
BuildNinja = 1 << iota
|
||||||
|
RunBuildTests = 1 << iota
|
||||||
BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
|
BuildAll = BuildProductConfig | BuildSoong | BuildKati | BuildNinja
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,14 +173,18 @@ func Build(ctx Context, config Config, what int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write combined ninja file
|
||||||
|
createCombinedBuildNinjaFile(ctx, config)
|
||||||
|
|
||||||
|
if what&RunBuildTests != 0 {
|
||||||
|
testForDanglingRules(ctx, config)
|
||||||
|
}
|
||||||
|
|
||||||
if what&BuildNinja != 0 {
|
if what&BuildNinja != 0 {
|
||||||
if !config.SkipMake() {
|
if !config.SkipMake() {
|
||||||
installCleanIfNecessary(ctx, config)
|
installCleanIfNecessary(ctx, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write combined ninja file
|
|
||||||
createCombinedBuildNinjaFile(ctx, config)
|
|
||||||
|
|
||||||
// Run ninja
|
// Run ninja
|
||||||
runNinja(ctx, config)
|
runNinja(ctx, config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,12 @@ type configImpl struct {
|
||||||
environ *Environment
|
environ *Environment
|
||||||
|
|
||||||
// From the arguments
|
// From the arguments
|
||||||
parallel int
|
parallel int
|
||||||
keepGoing int
|
keepGoing int
|
||||||
verbose bool
|
verbose bool
|
||||||
dist bool
|
checkbuild bool
|
||||||
skipMake bool
|
dist bool
|
||||||
|
skipMake bool
|
||||||
|
|
||||||
// From the product config
|
// From the product config
|
||||||
katiArgs []string
|
katiArgs []string
|
||||||
|
@ -206,6 +207,8 @@ func (c *configImpl) parseArgs(ctx Context, args []string) {
|
||||||
} else {
|
} else {
|
||||||
if arg == "dist" {
|
if arg == "dist" {
|
||||||
c.dist = true
|
c.dist = true
|
||||||
|
} else if arg == "checkbuild" {
|
||||||
|
c.checkbuild = true
|
||||||
}
|
}
|
||||||
c.arguments = append(c.arguments, arg)
|
c.arguments = append(c.arguments, arg)
|
||||||
}
|
}
|
||||||
|
@ -313,6 +316,12 @@ func (c *configImpl) KatiSuffix() string {
|
||||||
panic("SetKatiSuffix has not been called")
|
panic("SetKatiSuffix has not been called")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
|
||||||
|
// user is interested in additional checks at the expense of build time.
|
||||||
|
func (c *configImpl) Checkbuild() bool {
|
||||||
|
return c.checkbuild
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configImpl) Dist() bool {
|
func (c *configImpl) Dist() bool {
|
||||||
return c.dist
|
return c.dist
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
// Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Checks for files in the out directory that have a rule that depends on them but no rule to
|
||||||
|
// create them. This catches a common set of build failures where a rule to generate a file is
|
||||||
|
// deleted (either by deleting a module in an Android.mk file, or by modifying the build system
|
||||||
|
// incorrectly). These failures are often not caught by a local incremental build because the
|
||||||
|
// previously built files are still present in the output directory.
|
||||||
|
func testForDanglingRules(ctx Context, config Config) {
|
||||||
|
// Many modules are disabled on mac. Checking for dangling rules would cause lots of build
|
||||||
|
// breakages, and presubmit wouldn't catch them, so just disable the check.
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.BeginTrace("test for dangling rules")
|
||||||
|
defer ctx.EndTrace()
|
||||||
|
|
||||||
|
// Get a list of leaf nodes in the dependency graph from ninja
|
||||||
|
executable := config.PrebuiltBuildTool("ninja")
|
||||||
|
|
||||||
|
args := []string{}
|
||||||
|
args = append(args, config.NinjaArgs()...)
|
||||||
|
args = append(args, "-f", config.CombinedNinjaFile())
|
||||||
|
args = append(args, "-t", "targets", "rule")
|
||||||
|
|
||||||
|
cmd := Command(ctx, config, "ninja", executable, args...)
|
||||||
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.StartOrFatal()
|
||||||
|
|
||||||
|
outDir := config.OutDir()
|
||||||
|
bootstrapDir := filepath.Join(outDir, "soong", ".bootstrap")
|
||||||
|
miniBootstrapDir := filepath.Join(outDir, "soong", ".minibootstrap")
|
||||||
|
|
||||||
|
var danglingRules []string
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(stdout)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if !strings.HasPrefix(line, outDir) {
|
||||||
|
// Leaf node is not in the out directory.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(line, bootstrapDir) || strings.HasPrefix(line, miniBootstrapDir) {
|
||||||
|
// Leaf node is in one of Soong's bootstrap directories, which do not have
|
||||||
|
// full build rules in the primary build.ninja file.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
danglingRules = append(danglingRules, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.WaitOrFatal()
|
||||||
|
|
||||||
|
if len(danglingRules) > 0 {
|
||||||
|
ctx.Println("Dependencies in out found with no rule to create them:")
|
||||||
|
for _, dep := range danglingRules {
|
||||||
|
ctx.Println(dep)
|
||||||
|
}
|
||||||
|
ctx.Fatal("")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue