Add option to build and run tests during bootstrap
Users that want to enable this option can use the '-t' option to bootstrap.bash when passing '-r'. Builders that want to enable this can set the RUN_TESTS environment variable in their bootstrap.bash. The gotestmain tools is needed to write the main functions for the test binaries, since 'go test' doesn't work well in this environment. Change-Id: Iec5c2b5c9c3f5e3ba0ac8677fb88f5e963f9bd3f
This commit is contained in:
parent
30a80c3e5f
commit
87ba294ceb
7 changed files with 355 additions and 28 deletions
19
Blueprints
19
Blueprints
|
@ -19,6 +19,13 @@ bootstrap_go_package(
|
||||||
"singleton_ctx.go",
|
"singleton_ctx.go",
|
||||||
"unpack.go",
|
"unpack.go",
|
||||||
],
|
],
|
||||||
|
testSrcs = [
|
||||||
|
"context_test.go",
|
||||||
|
"ninja_strings_test.go",
|
||||||
|
"ninja_writer_test.go",
|
||||||
|
"splice_modules_test.go",
|
||||||
|
"unpack_test.go",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
bootstrap_go_package(
|
bootstrap_go_package(
|
||||||
|
@ -30,6 +37,10 @@ bootstrap_go_package(
|
||||||
"parser/printer.go",
|
"parser/printer.go",
|
||||||
"parser/sort.go",
|
"parser/sort.go",
|
||||||
],
|
],
|
||||||
|
testSrcs = [
|
||||||
|
"parser/parser_test.go",
|
||||||
|
"parser/printer_test.go",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
bootstrap_go_package(
|
bootstrap_go_package(
|
||||||
|
@ -45,6 +56,9 @@ bootstrap_go_package(
|
||||||
"pathtools/lists.go",
|
"pathtools/lists.go",
|
||||||
"pathtools/glob.go",
|
"pathtools/glob.go",
|
||||||
],
|
],
|
||||||
|
testSrcs = [
|
||||||
|
"pathtools/glob_test.go",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
bootstrap_go_package(
|
bootstrap_go_package(
|
||||||
|
@ -90,3 +104,8 @@ bootstrap_go_binary(
|
||||||
deps = ["blueprint-parser"],
|
deps = ["blueprint-parser"],
|
||||||
srcs = ["bpmodify/bpmodify.go"],
|
srcs = ["bpmodify/bpmodify.go"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
bootstrap_go_binary(
|
||||||
|
name = "gotestmain",
|
||||||
|
srcs = ["gotestmain/gotestmain.go"],
|
||||||
|
)
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
EXTRA_ARGS=""
|
||||||
|
|
||||||
# BOOTSTRAP should be set to the path of the bootstrap script. It can be
|
# BOOTSTRAP should be set to the path of the bootstrap script. It can be
|
||||||
# either an absolute path or one relative to the build directory (which of
|
# either an absolute path or one relative to the build directory (which of
|
||||||
# these is used should probably match what's used for SRCDIR).
|
# these is used should probably match what's used for SRCDIR).
|
||||||
|
@ -49,16 +51,20 @@ set -e
|
||||||
[ -z "$GOARCH" ] && GOARCH=`go env GOHOSTARCH`
|
[ -z "$GOARCH" ] && GOARCH=`go env GOHOSTARCH`
|
||||||
[ -z "$GOCHAR" ] && GOCHAR=`go env GOCHAR`
|
[ -z "$GOCHAR" ] && GOCHAR=`go env GOCHAR`
|
||||||
|
|
||||||
|
# If RUN_TESTS is set, behave like -t was passed in as an option.
|
||||||
|
[ ! -z "$RUN_TESTS" ] && EXTRA_ARGS="$EXTRA_ARGS -t"
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage of ${BOOTSTRAP}:"
|
echo "Usage of ${BOOTSTRAP}:"
|
||||||
echo " -h: print a help message and exit"
|
echo " -h: print a help message and exit"
|
||||||
echo " -r: regenerate ${BOOTSTRAP_MANIFEST}"
|
echo " -r: regenerate ${BOOTSTRAP_MANIFEST}"
|
||||||
|
echo " -t: include tests when regenerating manifest"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse the command line flags.
|
# Parse the command line flags.
|
||||||
IN="$BOOTSTRAP_MANIFEST"
|
IN="$BOOTSTRAP_MANIFEST"
|
||||||
REGEN_BOOTSTRAP_MANIFEST=false
|
REGEN_BOOTSTRAP_MANIFEST=false
|
||||||
while getopts ":hi:r" opt; do
|
while getopts ":hi:rt" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
h)
|
h)
|
||||||
usage
|
usage
|
||||||
|
@ -66,6 +72,7 @@ while getopts ":hi:r" opt; do
|
||||||
;;
|
;;
|
||||||
i) IN="$OPTARG";;
|
i) IN="$OPTARG";;
|
||||||
r) REGEN_BOOTSTRAP_MANIFEST=true;;
|
r) REGEN_BOOTSTRAP_MANIFEST=true;;
|
||||||
|
t) EXTRA_ARGS="$EXTRA_ARGS -t";;
|
||||||
\?)
|
\?)
|
||||||
echo "Invalid option: -$OPTARG" >&2
|
echo "Invalid option: -$OPTARG" >&2
|
||||||
usage
|
usage
|
||||||
|
@ -83,7 +90,7 @@ if [ $REGEN_BOOTSTRAP_MANIFEST = true ]; then
|
||||||
# that has been built in the past.
|
# that has been built in the past.
|
||||||
if [ -x .bootstrap/bin/minibp ]; then
|
if [ -x .bootstrap/bin/minibp ]; then
|
||||||
echo "Regenerating $BOOTSTRAP_MANIFEST"
|
echo "Regenerating $BOOTSTRAP_MANIFEST"
|
||||||
./.bootstrap/bin/minibp -o $BOOTSTRAP_MANIFEST $SRCDIR/$TOPNAME
|
./.bootstrap/bin/minibp $EXTRA_ARGS -o $BOOTSTRAP_MANIFEST $SRCDIR/$TOPNAME
|
||||||
else
|
else
|
||||||
echo "Executable minibp not found at .bootstrap/bin/minibp" >&2
|
echo "Executable minibp not found at .bootstrap/bin/minibp" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -31,6 +31,7 @@ var (
|
||||||
|
|
||||||
gcCmd = pctx.StaticVariable("gcCmd", "$goToolDir/${goChar}g")
|
gcCmd = pctx.StaticVariable("gcCmd", "$goToolDir/${goChar}g")
|
||||||
linkCmd = pctx.StaticVariable("linkCmd", "$goToolDir/${goChar}l")
|
linkCmd = pctx.StaticVariable("linkCmd", "$goToolDir/${goChar}l")
|
||||||
|
goTestMainCmd = pctx.StaticVariable("goTestMainCmd", filepath.Join(bootstrapDir, "bin", "gotestmain"))
|
||||||
|
|
||||||
// Ninja only reinvokes itself once when it regenerates a .ninja file. For
|
// Ninja only reinvokes itself once when it regenerates a .ninja file. For
|
||||||
// the re-bootstrap process we need that to happen more than once, so we
|
// the re-bootstrap process we need that to happen more than once, so we
|
||||||
|
@ -69,6 +70,20 @@ var (
|
||||||
},
|
},
|
||||||
"libDirFlags")
|
"libDirFlags")
|
||||||
|
|
||||||
|
goTestMain = pctx.StaticRule("gotestmain",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: "$goTestMainCmd -o $out -pkg $pkg $in",
|
||||||
|
Description: "gotestmain $out",
|
||||||
|
},
|
||||||
|
"pkg")
|
||||||
|
|
||||||
|
test = pctx.StaticRule("test",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: "(cd $pkgSrcDir && $$OLDPWD/$in -test.short) && touch $out",
|
||||||
|
Description: "test $pkg",
|
||||||
|
},
|
||||||
|
"pkg", "pkgSrcDir")
|
||||||
|
|
||||||
cp = pctx.StaticRule("cp",
|
cp = pctx.StaticRule("cp",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
Command: "cp $in $out",
|
Command: "cp $in $out",
|
||||||
|
@ -113,6 +128,15 @@ func isGoPackageProducer(module blueprint.Module) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type goTestProducer interface {
|
||||||
|
GoTestTarget() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGoTestProducer(module blueprint.Module) bool {
|
||||||
|
_, ok := module.(goTestProducer)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func isBootstrapModule(module blueprint.Module) bool {
|
func isBootstrapModule(module blueprint.Module) bool {
|
||||||
_, isPackage := module.(*goPackage)
|
_, isPackage := module.(*goPackage)
|
||||||
_, isBinary := module.(*goBinary)
|
_, isBinary := module.(*goBinary)
|
||||||
|
@ -140,6 +164,7 @@ type goPackage struct {
|
||||||
properties struct {
|
properties struct {
|
||||||
PkgPath string
|
PkgPath string
|
||||||
Srcs []string
|
Srcs []string
|
||||||
|
TestSrcs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// The root dir in which the package .a file is located. The full .a file
|
// The root dir in which the package .a file is located. The full .a file
|
||||||
|
@ -149,6 +174,9 @@ type goPackage struct {
|
||||||
// The path of the .a file that is to be built.
|
// The path of the .a file that is to be built.
|
||||||
archiveFile string
|
archiveFile string
|
||||||
|
|
||||||
|
// The path of the test .a file that is to be built.
|
||||||
|
testArchiveFile string
|
||||||
|
|
||||||
// The bootstrap Config
|
// The bootstrap Config
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
@ -172,6 +200,10 @@ func (g *goPackage) GoPackageTarget() string {
|
||||||
return g.archiveFile
|
return g.archiveFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *goPackage) GoTestTarget() string {
|
||||||
|
return g.testArchiveFile
|
||||||
|
}
|
||||||
|
|
||||||
func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
name := ctx.ModuleName()
|
name := ctx.ModuleName()
|
||||||
|
|
||||||
|
@ -181,8 +213,12 @@ func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
g.pkgRoot = packageRoot(ctx)
|
g.pkgRoot = packageRoot(ctx)
|
||||||
g.archiveFile = filepath.Clean(filepath.Join(g.pkgRoot,
|
g.archiveFile = filepath.Join(g.pkgRoot,
|
||||||
filepath.FromSlash(g.properties.PkgPath)+".a"))
|
filepath.FromSlash(g.properties.PkgPath)+".a")
|
||||||
|
if len(g.properties.TestSrcs) > 0 && g.config.runGoTests {
|
||||||
|
g.testArchiveFile = filepath.Join(testRoot(ctx),
|
||||||
|
filepath.FromSlash(g.properties.PkgPath)+".a")
|
||||||
|
}
|
||||||
|
|
||||||
// We only actually want to build the builder modules if we're running as
|
// We only actually want to build the builder modules if we're running as
|
||||||
// minibp (i.e. we're generating a bootstrap Ninja file). This is to break
|
// minibp (i.e. we're generating a bootstrap Ninja file). This is to break
|
||||||
|
@ -190,9 +226,20 @@ func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
// file to be built, but building a new ninja file requires the builder to
|
// file to be built, but building a new ninja file requires the builder to
|
||||||
// be built.
|
// be built.
|
||||||
if g.config.generatingBootstrapper {
|
if g.config.generatingBootstrapper {
|
||||||
|
var deps []string
|
||||||
|
|
||||||
|
if g.config.runGoTests {
|
||||||
|
deps = buildGoTest(ctx, testRoot(ctx), g.testArchiveFile,
|
||||||
|
g.properties.PkgPath, g.properties.Srcs,
|
||||||
|
g.properties.TestSrcs)
|
||||||
|
}
|
||||||
|
|
||||||
buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile,
|
buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile,
|
||||||
g.properties.Srcs)
|
g.properties.Srcs, deps)
|
||||||
} else {
|
} else {
|
||||||
|
if len(g.properties.TestSrcs) > 0 && g.config.runGoTests {
|
||||||
|
phonyGoTarget(ctx, g.testArchiveFile, g.properties.TestSrcs, nil)
|
||||||
|
}
|
||||||
phonyGoTarget(ctx, g.archiveFile, g.properties.Srcs, nil)
|
phonyGoTarget(ctx, g.archiveFile, g.properties.Srcs, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,9 +248,13 @@ func (g *goPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
type goBinary struct {
|
type goBinary struct {
|
||||||
properties struct {
|
properties struct {
|
||||||
Srcs []string
|
Srcs []string
|
||||||
|
TestSrcs []string
|
||||||
PrimaryBuilder bool
|
PrimaryBuilder bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The path of the test .a file that is to be built.
|
||||||
|
testArchiveFile string
|
||||||
|
|
||||||
// The bootstrap Config
|
// The bootstrap Config
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
@ -217,6 +268,10 @@ func newGoBinaryModuleFactory(config *Config) func() (blueprint.Module, []interf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *goBinary) GoTestTarget() string {
|
||||||
|
return g.testArchiveFile
|
||||||
|
}
|
||||||
|
|
||||||
func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
var (
|
var (
|
||||||
name = ctx.ModuleName()
|
name = ctx.ModuleName()
|
||||||
|
@ -226,13 +281,24 @@ func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
binaryFile = filepath.Join(BinDir, name)
|
binaryFile = filepath.Join(BinDir, name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if len(g.properties.TestSrcs) > 0 && g.config.runGoTests {
|
||||||
|
g.testArchiveFile = filepath.Join(testRoot(ctx), name+".a")
|
||||||
|
}
|
||||||
|
|
||||||
// We only actually want to build the builder modules if we're running as
|
// We only actually want to build the builder modules if we're running as
|
||||||
// minibp (i.e. we're generating a bootstrap Ninja file). This is to break
|
// minibp (i.e. we're generating a bootstrap Ninja file). This is to break
|
||||||
// the circular dependence that occurs when the builder requires a new Ninja
|
// the circular dependence that occurs when the builder requires a new Ninja
|
||||||
// file to be built, but building a new ninja file requires the builder to
|
// file to be built, but building a new ninja file requires the builder to
|
||||||
// be built.
|
// be built.
|
||||||
if g.config.generatingBootstrapper {
|
if g.config.generatingBootstrapper {
|
||||||
buildGoPackage(ctx, objDir, name, archiveFile, g.properties.Srcs)
|
var deps []string
|
||||||
|
|
||||||
|
if g.config.runGoTests {
|
||||||
|
deps = buildGoTest(ctx, testRoot(ctx), g.testArchiveFile,
|
||||||
|
name, g.properties.Srcs, g.properties.TestSrcs)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildGoPackage(ctx, objDir, name, archiveFile, g.properties.Srcs, deps)
|
||||||
|
|
||||||
var libDirFlags []string
|
var libDirFlags []string
|
||||||
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
||||||
|
@ -261,13 +327,17 @@ func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
Inputs: []string{aoutFile},
|
Inputs: []string{aoutFile},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
if len(g.properties.TestSrcs) > 0 && g.config.runGoTests {
|
||||||
|
phonyGoTarget(ctx, g.testArchiveFile, g.properties.TestSrcs, nil)
|
||||||
|
}
|
||||||
|
|
||||||
intermediates := []string{aoutFile, archiveFile}
|
intermediates := []string{aoutFile, archiveFile}
|
||||||
phonyGoTarget(ctx, binaryFile, g.properties.Srcs, intermediates)
|
phonyGoTarget(ctx, binaryFile, g.properties.Srcs, intermediates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
|
func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
|
||||||
pkgPath string, archiveFile string, srcs []string) {
|
pkgPath string, archiveFile string, srcs []string, orderDeps []string) {
|
||||||
|
|
||||||
srcDir := moduleSrcDir(ctx)
|
srcDir := moduleSrcDir(ctx)
|
||||||
srcFiles := pathtools.PrefixPaths(srcs, srcDir)
|
srcFiles := pathtools.PrefixPaths(srcs, srcDir)
|
||||||
|
@ -295,11 +365,83 @@ func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
|
||||||
Rule: gc,
|
Rule: gc,
|
||||||
Outputs: []string{archiveFile},
|
Outputs: []string{archiveFile},
|
||||||
Inputs: srcFiles,
|
Inputs: srcFiles,
|
||||||
|
OrderOnly: orderDeps,
|
||||||
Implicits: deps,
|
Implicits: deps,
|
||||||
Args: gcArgs,
|
Args: gcArgs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildGoTest(ctx blueprint.ModuleContext, testRoot string,
|
||||||
|
testPkgArchive string, pkgPath string, srcs []string,
|
||||||
|
testSrcs []string) []string {
|
||||||
|
|
||||||
|
if len(testSrcs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
srcDir := moduleSrcDir(ctx)
|
||||||
|
testFiles := pathtools.PrefixPaths(testSrcs, srcDir)
|
||||||
|
|
||||||
|
mainFile := filepath.Join(testRoot, "test.go")
|
||||||
|
testArchive := filepath.Join(testRoot, "test.a")
|
||||||
|
testFile := filepath.Join(testRoot, "test")
|
||||||
|
testPassed := filepath.Join(testRoot, "test.passed")
|
||||||
|
|
||||||
|
buildGoPackage(ctx, testRoot, pkgPath, testPkgArchive,
|
||||||
|
append(srcs, testSrcs...), nil)
|
||||||
|
|
||||||
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
|
Rule: goTestMain,
|
||||||
|
Outputs: []string{mainFile},
|
||||||
|
Inputs: testFiles,
|
||||||
|
Implicits: []string{"$goTestMainCmd"},
|
||||||
|
Args: map[string]string{
|
||||||
|
"pkg": pkgPath,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
libDirFlags := []string{"-L " + testRoot}
|
||||||
|
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
||||||
|
func(module blueprint.Module) {
|
||||||
|
dep := module.(goPackageProducer)
|
||||||
|
libDir := dep.GoPkgRoot()
|
||||||
|
libDirFlags = append(libDirFlags, "-L "+libDir)
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
|
Rule: gc,
|
||||||
|
Outputs: []string{testArchive},
|
||||||
|
Inputs: []string{mainFile},
|
||||||
|
Implicits: []string{testPkgArchive},
|
||||||
|
Args: map[string]string{
|
||||||
|
"pkgPath": "main",
|
||||||
|
"incFlags": "-I " + testRoot,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
|
Rule: link,
|
||||||
|
Outputs: []string{testFile},
|
||||||
|
Inputs: []string{testArchive},
|
||||||
|
Implicits: []string{"$linkCmd"},
|
||||||
|
Args: map[string]string{
|
||||||
|
"libDirFlags": strings.Join(libDirFlags, " "),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
|
Rule: test,
|
||||||
|
Outputs: []string{testPassed},
|
||||||
|
Inputs: []string{testFile},
|
||||||
|
Args: map[string]string{
|
||||||
|
"pkg": pkgPath,
|
||||||
|
"pkgSrcDir": filepath.Dir(testFiles[0]),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return []string{testPassed}
|
||||||
|
}
|
||||||
|
|
||||||
func phonyGoTarget(ctx blueprint.ModuleContext, target string, srcs []string,
|
func phonyGoTarget(ctx blueprint.ModuleContext, target string, srcs []string,
|
||||||
intermediates []string) {
|
intermediates []string) {
|
||||||
|
|
||||||
|
@ -398,6 +540,10 @@ func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
|
||||||
|
|
||||||
primaryBuilderFile := filepath.Join(BinDir, primaryBuilderName)
|
primaryBuilderFile := filepath.Join(BinDir, primaryBuilderName)
|
||||||
|
|
||||||
|
if s.config.runGoTests {
|
||||||
|
primaryBuilderExtraFlags += " -t"
|
||||||
|
}
|
||||||
|
|
||||||
// Get the filename of the top-level Blueprints file to pass to minibp.
|
// Get the filename of the top-level Blueprints file to pass to minibp.
|
||||||
// This comes stored in a global variable that's set by Main.
|
// This comes stored in a global variable that's set by Main.
|
||||||
topLevelBlueprints := filepath.Join("$srcDir",
|
topLevelBlueprints := filepath.Join("$srcDir",
|
||||||
|
@ -469,24 +615,40 @@ func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
|
||||||
// and it will trigger a reboostrap by the non-boostrap build manifest.
|
// and it will trigger a reboostrap by the non-boostrap build manifest.
|
||||||
minibp := ctx.Rule(pctx, "minibp",
|
minibp := ctx.Rule(pctx, "minibp",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
Command: fmt.Sprintf("%s -c $checkFile -m $bootstrapManifest "+
|
Command: fmt.Sprintf("%s $runTests -c $checkFile -m $bootstrapManifest "+
|
||||||
"-d $out.d -o $out $in", minibpFile),
|
"-d $out.d -o $out $in", minibpFile),
|
||||||
Description: "minibp $out",
|
Description: "minibp $out",
|
||||||
Generator: true,
|
Generator: true,
|
||||||
Depfile: "$out.d",
|
Depfile: "$out.d",
|
||||||
},
|
},
|
||||||
"checkFile")
|
"checkFile", "runTests")
|
||||||
|
|
||||||
|
args := map[string]string{
|
||||||
|
"checkFile": "$bootstrapManifest",
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.config.runGoTests {
|
||||||
|
args["runTests"] = "-t"
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Build(pctx, blueprint.BuildParams{
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
Rule: minibp,
|
Rule: minibp,
|
||||||
Outputs: []string{bootstrapNinjaFile},
|
Outputs: []string{bootstrapNinjaFile},
|
||||||
Inputs: []string{topLevelBlueprints},
|
Inputs: []string{topLevelBlueprints},
|
||||||
Implicits: []string{minibpFile},
|
Implicits: []string{minibpFile},
|
||||||
Args: map[string]string{
|
Args: args,
|
||||||
"checkFile": "$bootstrapManifest",
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
var allGoTests []string
|
||||||
|
ctx.VisitAllModulesIf(isGoTestProducer,
|
||||||
|
func(module blueprint.Module) {
|
||||||
|
testModule := module.(goTestProducer)
|
||||||
|
target := testModule.GoTestTarget()
|
||||||
|
if target != "" {
|
||||||
|
allGoTests = append(allGoTests, target)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// We're generating a non-bootstrapper Ninja file, so we need to set it
|
// We're generating a non-bootstrapper Ninja file, so we need to set it
|
||||||
// up to depend on the bootstrapper Ninja file. The build.ninja target
|
// up to depend on the bootstrapper Ninja file. The build.ninja target
|
||||||
// also has an implicit dependency on the primary builder and all other
|
// also has an implicit dependency on the primary builder and all other
|
||||||
|
@ -500,6 +662,7 @@ func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
|
||||||
// phony rule to generate it that uses the depfile.
|
// phony rule to generate it that uses the depfile.
|
||||||
buildNinjaDeps := []string{"$bootstrapCmd", mainNinjaFile}
|
buildNinjaDeps := []string{"$bootstrapCmd", mainNinjaFile}
|
||||||
buildNinjaDeps = append(buildNinjaDeps, allGoBinaries...)
|
buildNinjaDeps = append(buildNinjaDeps, allGoBinaries...)
|
||||||
|
buildNinjaDeps = append(buildNinjaDeps, allGoTests...)
|
||||||
ctx.Build(pctx, blueprint.BuildParams{
|
ctx.Build(pctx, blueprint.BuildParams{
|
||||||
Rule: rebootstrap,
|
Rule: rebootstrap,
|
||||||
Outputs: []string{"build.ninja"},
|
Outputs: []string{"build.ninja"},
|
||||||
|
@ -550,6 +713,13 @@ func packageRoot(ctx blueprint.ModuleContext) string {
|
||||||
return filepath.Join(bootstrapDir, ctx.ModuleName(), "pkg")
|
return filepath.Join(bootstrapDir, ctx.ModuleName(), "pkg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testRoot returns the module-specific package root directory path used for
|
||||||
|
// building tests. The .a files generated here will include everything from
|
||||||
|
// packageRoot, plus the test-only code.
|
||||||
|
func testRoot(ctx blueprint.ModuleContext) string {
|
||||||
|
return filepath.Join(bootstrapDir, ctx.ModuleName(), "test")
|
||||||
|
}
|
||||||
|
|
||||||
// moduleSrcDir returns the path of the directory that all source file paths are
|
// moduleSrcDir returns the path of the directory that all source file paths are
|
||||||
// specified relative to.
|
// specified relative to.
|
||||||
func moduleSrcDir(ctx blueprint.ModuleContext) string {
|
func moduleSrcDir(ctx blueprint.ModuleContext) string {
|
||||||
|
|
|
@ -34,6 +34,7 @@ var (
|
||||||
checkFile string
|
checkFile string
|
||||||
manifestFile string
|
manifestFile string
|
||||||
cpuprofile string
|
cpuprofile string
|
||||||
|
runGoTests bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -42,6 +43,7 @@ func init() {
|
||||||
flag.StringVar(&checkFile, "c", "", "the existing file to check against")
|
flag.StringVar(&checkFile, "c", "", "the existing file to check against")
|
||||||
flag.StringVar(&manifestFile, "m", "", "the bootstrap manifest file")
|
flag.StringVar(&manifestFile, "m", "", "the bootstrap manifest file")
|
||||||
flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
|
flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
|
||||||
|
flag.BoolVar(&runGoTests, "t", false, "build and run go tests during bootstrap")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...string) {
|
func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...string) {
|
||||||
|
@ -73,6 +75,7 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri
|
||||||
bootstrapConfig := &Config{
|
bootstrapConfig := &Config{
|
||||||
generatingBootstrapper: generatingBootstrapper,
|
generatingBootstrapper: generatingBootstrapper,
|
||||||
topLevelBlueprintsFile: flag.Arg(0),
|
topLevelBlueprintsFile: flag.Arg(0),
|
||||||
|
runGoTests: runGoTests,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.RegisterModuleType("bootstrap_go_package", newGoPackageModuleFactory(bootstrapConfig))
|
ctx.RegisterModuleType("bootstrap_go_package", newGoPackageModuleFactory(bootstrapConfig))
|
||||||
|
|
|
@ -45,4 +45,6 @@ type Config struct {
|
||||||
generatingBootstrapper bool
|
generatingBootstrapper bool
|
||||||
|
|
||||||
topLevelBlueprintsFile string
|
topLevelBlueprintsFile string
|
||||||
|
|
||||||
|
runGoTests bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ default .bootstrap/blueprint/pkg/github.com/google/blueprint.a
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·002
|
# Factory: github.com/google/blueprint/bootstrap.func·002
|
||||||
# Defined: Blueprints:56:1
|
# Defined: Blueprints:70:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
|
.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
|
||||||
|
@ -100,7 +100,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·002
|
# Factory: github.com/google/blueprint/bootstrap.func·002
|
||||||
# Defined: Blueprints:35:1
|
# Defined: Blueprints:46:1
|
||||||
|
|
||||||
build .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
|
build .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
|
||||||
: g.bootstrap.gc ${g.bootstrap.srcDir}/deptools/depfile.go | $
|
: g.bootstrap.gc ${g.bootstrap.srcDir}/deptools/depfile.go | $
|
||||||
|
@ -114,7 +114,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·002
|
# Factory: github.com/google/blueprint/bootstrap.func·002
|
||||||
# Defined: Blueprints:24:1
|
# Defined: Blueprints:31:1
|
||||||
|
|
||||||
build .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a: $
|
build .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a: $
|
||||||
g.bootstrap.gc ${g.bootstrap.srcDir}/parser/modify.go $
|
g.bootstrap.gc ${g.bootstrap.srcDir}/parser/modify.go $
|
||||||
|
@ -129,7 +129,7 @@ default .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·002
|
# Factory: github.com/google/blueprint/bootstrap.func·002
|
||||||
# Defined: Blueprints:41:1
|
# Defined: Blueprints:52:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
|
.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
|
||||||
|
@ -144,7 +144,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·002
|
# Factory: github.com/google/blueprint/bootstrap.func·002
|
||||||
# Defined: Blueprints:50:1
|
# Defined: Blueprints:64:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
|
.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
|
||||||
|
@ -159,7 +159,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_binary
|
# Type: bootstrap_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·003
|
# Factory: github.com/google/blueprint/bootstrap.func·003
|
||||||
# Defined: Blueprints:82:1
|
# Defined: Blueprints:96:1
|
||||||
|
|
||||||
build .bootstrap/bpfmt/obj/bpfmt.a: g.bootstrap.gc $
|
build .bootstrap/bpfmt/obj/bpfmt.a: g.bootstrap.gc $
|
||||||
${g.bootstrap.srcDir}/bpfmt/bpfmt.go | ${g.bootstrap.gcCmd} $
|
${g.bootstrap.srcDir}/bpfmt/bpfmt.go | ${g.bootstrap.gcCmd} $
|
||||||
|
@ -181,7 +181,7 @@ default .bootstrap/bin/bpfmt
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_binary
|
# Type: bootstrap_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·003
|
# Factory: github.com/google/blueprint/bootstrap.func·003
|
||||||
# Defined: Blueprints:88:1
|
# Defined: Blueprints:102:1
|
||||||
|
|
||||||
build .bootstrap/bpmodify/obj/bpmodify.a: g.bootstrap.gc $
|
build .bootstrap/bpmodify/obj/bpmodify.a: g.bootstrap.gc $
|
||||||
${g.bootstrap.srcDir}/bpmodify/bpmodify.go | ${g.bootstrap.gcCmd} $
|
${g.bootstrap.srcDir}/bpmodify/bpmodify.go | ${g.bootstrap.gcCmd} $
|
||||||
|
@ -198,12 +198,31 @@ default .bootstrap/bpmodify/obj/a.out
|
||||||
build .bootstrap/bin/bpmodify: g.bootstrap.cp .bootstrap/bpmodify/obj/a.out
|
build .bootstrap/bin/bpmodify: g.bootstrap.cp .bootstrap/bpmodify/obj/a.out
|
||||||
default .bootstrap/bin/bpmodify
|
default .bootstrap/bin/bpmodify
|
||||||
|
|
||||||
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
|
# Module: gotestmain
|
||||||
|
# Variant:
|
||||||
|
# Type: bootstrap_go_binary
|
||||||
|
# Factory: github.com/google/blueprint/bootstrap.func·003
|
||||||
|
# Defined: Blueprints:108:1
|
||||||
|
|
||||||
|
build .bootstrap/gotestmain/obj/gotestmain.a: g.bootstrap.gc $
|
||||||
|
${g.bootstrap.srcDir}/gotestmain/gotestmain.go | ${g.bootstrap.gcCmd}
|
||||||
|
pkgPath = gotestmain
|
||||||
|
default .bootstrap/gotestmain/obj/gotestmain.a
|
||||||
|
|
||||||
|
build .bootstrap/gotestmain/obj/a.out: g.bootstrap.link $
|
||||||
|
.bootstrap/gotestmain/obj/gotestmain.a | ${g.bootstrap.linkCmd}
|
||||||
|
default .bootstrap/gotestmain/obj/a.out
|
||||||
|
build .bootstrap/bin/gotestmain: g.bootstrap.cp $
|
||||||
|
.bootstrap/gotestmain/obj/a.out
|
||||||
|
default .bootstrap/bin/gotestmain
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# Module: minibp
|
# Module: minibp
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_binary
|
# Type: bootstrap_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·003
|
# Factory: github.com/google/blueprint/bootstrap.func·003
|
||||||
# Defined: Blueprints:73:1
|
# Defined: Blueprints:87:1
|
||||||
|
|
||||||
build .bootstrap/minibp/obj/minibp.a: g.bootstrap.gc $
|
build .bootstrap/minibp/obj/minibp.a: g.bootstrap.gc $
|
||||||
${g.bootstrap.srcDir}/bootstrap/minibp/main.go | ${g.bootstrap.gcCmd} $
|
${g.bootstrap.srcDir}/bootstrap/minibp/main.go | ${g.bootstrap.gcCmd} $
|
||||||
|
@ -227,7 +246,7 @@ default .bootstrap/bin/minibp
|
||||||
|
|
||||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||||
# Singleton: bootstrap
|
# Singleton: bootstrap
|
||||||
# Factory: github.com/google/blueprint/bootstrap.func·007
|
# Factory: github.com/google/blueprint/bootstrap.func·008
|
||||||
|
|
||||||
rule s.bootstrap.bigbp
|
rule s.bootstrap.bigbp
|
||||||
command = .bootstrap/bin/minibp -p -d .bootstrap/main.ninja.in.d -m ${g.bootstrap.bootstrapManifest} -o ${out} ${in}
|
command = .bootstrap/bin/minibp -p -d .bootstrap/main.ninja.in.d -m ${g.bootstrap.bootstrapManifest} -o ${out} ${in}
|
||||||
|
@ -235,14 +254,15 @@ rule s.bootstrap.bigbp
|
||||||
description = minibp ${out}
|
description = minibp ${out}
|
||||||
|
|
||||||
rule s.bootstrap.minibp
|
rule s.bootstrap.minibp
|
||||||
command = .bootstrap/bin/minibp -c ${checkFile} -m ${g.bootstrap.bootstrapManifest} -d ${out}.d -o ${out} ${in}
|
command = .bootstrap/bin/minibp ${runTests} -c ${checkFile} -m ${g.bootstrap.bootstrapManifest} -d ${out}.d -o ${out} ${in}
|
||||||
depfile = ${out}.d
|
depfile = ${out}.d
|
||||||
description = minibp ${out}
|
description = minibp ${out}
|
||||||
generator = true
|
generator = true
|
||||||
|
|
||||||
build .bootstrap/main.ninja.in: s.bootstrap.bigbp $
|
build .bootstrap/main.ninja.in: s.bootstrap.bigbp $
|
||||||
${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/bpfmt $
|
${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/bpfmt $
|
||||||
.bootstrap/bin/bpmodify .bootstrap/bin/minibp
|
.bootstrap/bin/bpmodify .bootstrap/bin/gotestmain $
|
||||||
|
.bootstrap/bin/minibp
|
||||||
default .bootstrap/main.ninja.in
|
default .bootstrap/main.ninja.in
|
||||||
build .bootstrap/notAFile: phony
|
build .bootstrap/notAFile: phony
|
||||||
default .bootstrap/notAFile
|
default .bootstrap/notAFile
|
||||||
|
|
106
gotestmain/gotestmain.go
Normal file
106
gotestmain/gotestmain.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2015 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 gotestmain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
output = flag.String("o", "", "output filename")
|
||||||
|
pkg = flag.String("pkg", "", "test package")
|
||||||
|
exitCode = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
type data struct {
|
||||||
|
Package string
|
||||||
|
Tests []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func findTests(srcs []string) (tests []string) {
|
||||||
|
for _, src := range srcs {
|
||||||
|
f, err := parser.ParseFile(token.NewFileSet(), src, nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, obj := range f.Scope.Objects {
|
||||||
|
if obj.Kind != ast.Fun || !strings.HasPrefix(obj.Name, "Test") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tests = append(tests, obj.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if flag.NArg() == 0 {
|
||||||
|
fmt.Fprintln(os.Stderr, "error: must pass at least one input")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
d := data{
|
||||||
|
Package: *pkg,
|
||||||
|
Tests: findTests(flag.Args()),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := testMainTmpl.Execute(buf, d)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(*output, buf.Bytes(), 0666)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testMainTmpl = template.Must(template.New("testMain").Parse(`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
pkg "{{.Package}}"
|
||||||
|
)
|
||||||
|
|
||||||
|
var t = []testing.InternalTest{
|
||||||
|
{{range .Tests}}
|
||||||
|
{"{{.}}", pkg.{{.}}},
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchString(pat, str string) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
testing.Main(matchString, t, nil, nil)
|
||||||
|
}
|
||||||
|
`))
|
Loading…
Reference in a new issue