Allow multiple ninja implementations

This permits easier testing and comparison between different ninja
implementations.

Bug: 362926979
Bug: 318434287
Test: manual
Change-Id: Ic058338d0a2fd8c988794a0781dcc93c0f4c03e3
This commit is contained in:
LaMont Jones
2024-09-03 11:19:31 -07:00
parent 82e99ce373
commit ece626ccac
3 changed files with 113 additions and 54 deletions

View File

@@ -54,6 +54,16 @@ func init() {
rbeRandPrefix = rand.Intn(1000) rbeRandPrefix = rand.Intn(1000)
} }
// Which builder are we using?
type ninjaCommandType = int
const (
_ = iota
NINJA_NINJA
NINJA_N2
NINJA_SISO
)
type Config struct{ *configImpl } type Config struct{ *configImpl }
type configImpl struct { type configImpl struct {
@@ -123,9 +133,8 @@ type configImpl struct {
// could consider merging them. // could consider merging them.
moduleDebugFile string moduleDebugFile string
// Whether to use n2 instead of ninja. This is controlled with the // Which builder are we using
// environment variable SOONG_USE_N2 ninjaCommand ninjaCommandType
useN2 bool
} }
type NinjaWeightListSource uint type NinjaWeightListSource uint
@@ -288,8 +297,16 @@ func NewConfig(ctx Context, args ...string) Config {
ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json")) ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
} }
if os.Getenv("SOONG_USE_N2") == "true" { ret.ninjaCommand = NINJA_NINJA
ret.useN2 = true switch os.Getenv("SOONG_NINJA") {
case "n2":
ret.ninjaCommand = NINJA_N2
case "siso":
ret.ninjaCommand = NINJA_SISO
default:
if os.Getenv("SOONG_USE_N2") == "true" {
ret.ninjaCommand = NINJA_N2
}
} }
ret.environ.Unset( ret.environ.Unset(
@@ -349,7 +366,8 @@ func NewConfig(ctx Context, args ...string) Config {
// We read it here already, don't let others share in the fun // We read it here already, don't let others share in the fun
"GENERATE_SOONG_DEBUG", "GENERATE_SOONG_DEBUG",
// Use config.useN2 instead. // Use config.ninjaCommand instead.
"SOONG_NINJA",
"SOONG_USE_N2", "SOONG_USE_N2",
) )
@@ -1641,6 +1659,12 @@ func (c *configImpl) N2Bin() string {
return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/") return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
} }
func (c *configImpl) SisoBin() string {
path := c.PrebuiltBuildTool("siso")
// Use musl instead of glibc because glibc on the build server is old and has bugs
return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
}
func (c *configImpl) PrebuiltBuildTool(name string) string { func (c *configImpl) PrebuiltBuildTool(name string) string {
if v, ok := c.environ.Get("SANITIZE_HOST"); ok { if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
if sanitize := strings.Fields(v); inList("address", sanitize) { if sanitize := strings.Fields(v); inList("address", sanitize) {

View File

@@ -49,14 +49,10 @@ func runNinjaForBuild(ctx Context, config Config) {
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo) nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close() defer nr.Close()
executable := config.NinjaBin() var executable string
args := []string{ var args []string
"-d", "keepdepfile", switch config.ninjaCommand {
"-d", "keeprsp", case NINJA_N2:
"-d", "stats",
"--frontend_file", fifo,
}
if config.useN2 {
executable = config.N2Bin() executable = config.N2Bin()
args = []string{ args = []string{
"-d", "trace", "-d", "trace",
@@ -66,8 +62,31 @@ func runNinjaForBuild(ctx Context, config Config) {
//"-d", "stats", //"-d", "stats",
"--frontend-file", fifo, "--frontend-file", fifo,
} }
case NINJA_SISO:
executable = config.SisoBin()
args = []string{
"ninja",
"--log_dir", config.SoongOutDir(),
// TODO: implement these features, or remove them.
//"-d", "trace",
//"-d", "keepdepfile",
//"-d", "keeprsp",
//"-d", "stats",
//"--frontend-file", fifo,
}
default:
// NINJA_NINJA is the default.
executable = config.NinjaBin()
args = []string{
"-d", "keepdepfile",
"-d", "keeprsp",
"-d", "stats",
"--frontend_file", fifo,
"-o", "usesphonyoutputs=yes",
"-w", "dupbuild=err",
"-w", "missingdepfile=err",
}
} }
args = append(args, config.NinjaArgs()...) args = append(args, config.NinjaArgs()...)
var parallel int var parallel int
@@ -83,17 +102,10 @@ func runNinjaForBuild(ctx Context, config Config) {
args = append(args, "-f", config.CombinedNinjaFile()) args = append(args, "-f", config.CombinedNinjaFile())
if !config.useN2 {
args = append(args,
"-o", "usesphonyoutputs=yes",
"-w", "dupbuild=err",
"-w", "missingdepfile=err")
}
if !config.BuildBrokenMissingOutputs() { if !config.BuildBrokenMissingOutputs() {
// Missing outputs will be treated as errors. // Missing outputs will be treated as errors.
// BUILD_BROKEN_MISSING_OUTPUTS can be used to bypass this check. // BUILD_BROKEN_MISSING_OUTPUTS can be used to bypass this check.
if !config.useN2 { if config.ninjaCommand != NINJA_N2 {
args = append(args, args = append(args,
"-w", "missingoutfile=err", "-w", "missingoutfile=err",
) )
@@ -110,21 +122,18 @@ func runNinjaForBuild(ctx Context, config Config) {
cmd.Environment.AppendFromKati(config.KatiEnvFile()) cmd.Environment.AppendFromKati(config.KatiEnvFile())
} }
switch config.NinjaWeightListSource() { // TODO(b/346806126): implement this for the other ninjaCommand values.
case NINJA_LOG: if config.ninjaCommand == NINJA_NINJA {
if !config.useN2 { switch config.NinjaWeightListSource() {
case NINJA_LOG:
cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes") cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes")
} case EVENLY_DISTRIBUTED:
case EVENLY_DISTRIBUTED: // pass empty weight list means ninja considers every tasks's weight as 1(default value).
// pass empty weight list means ninja considers every tasks's weight as 1(default value).
if !config.useN2 {
cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null") cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
} case EXTERNAL_FILE:
case EXTERNAL_FILE: fallthrough
fallthrough case HINT_FROM_SOONG:
case HINT_FROM_SOONG: // The weight list is already copied/generated.
// The weight list is already copied/generated.
if !config.useN2 {
ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName) ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName)
cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath) cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath)
} }
@@ -227,6 +236,8 @@ func runNinjaForBuild(ctx Context, config Config) {
// We don't want this build broken flag to cause reanalysis, so allow it through to the // We don't want this build broken flag to cause reanalysis, so allow it through to the
// actions. // actions.
"BUILD_BROKEN_INCORRECT_PARTITION_IMAGES", "BUILD_BROKEN_INCORRECT_PARTITION_IMAGES",
// Do not do reanalysis just because we changed ninja commands.
"SOONG_NINJA",
"SOONG_USE_N2", "SOONG_USE_N2",
"RUST_BACKTRACE", "RUST_BACKTRACE",
"RUST_LOG", "RUST_LOG",
@@ -235,8 +246,11 @@ func runNinjaForBuild(ctx Context, config Config) {
cmd.Environment.Set("DIST_DIR", config.DistDir()) cmd.Environment.Set("DIST_DIR", config.DistDir())
cmd.Environment.Set("SHELL", "/bin/bash") cmd.Environment.Set("SHELL", "/bin/bash")
if config.useN2 { switch config.ninjaCommand {
case NINJA_N2:
cmd.Environment.Set("RUST_BACKTRACE", "1") cmd.Environment.Set("RUST_BACKTRACE", "1")
default:
// Only set RUST_BACKTRACE for n2.
} }
// Print the environment variables that Ninja is operating in. // Print the environment variables that Ninja is operating in.

View File

@@ -588,19 +588,11 @@ func runSoong(ctx Context, config Config) {
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo) nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close() defer nr.Close()
ninjaArgs := []string{ var ninjaCmd string
"-d", "keepdepfile", var ninjaArgs []string
"-d", "stats", switch config.ninjaCommand {
"-o", "usesphonyoutputs=yes", case NINJA_N2:
"-o", "preremoveoutputs=yes", ninjaCmd = config.N2Bin()
"-w", "dupbuild=err",
"-w", "outputdir=err",
"-w", "missingoutfile=err",
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
}
if config.useN2 {
ninjaArgs = []string{ ninjaArgs = []string{
// TODO: implement these features, or remove them. // TODO: implement these features, or remove them.
//"-d", "keepdepfile", //"-d", "keepdepfile",
@@ -615,6 +607,39 @@ func runSoong(ctx Context, config Config) {
"--frontend-file", fifo, "--frontend-file", fifo,
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"), "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
} }
case NINJA_SISO:
ninjaCmd = config.SisoBin()
ninjaArgs = []string{
"ninja",
// TODO: implement these features, or remove them.
//"-d", "keepdepfile",
//"-d", "stats",
//"-o", "usesphonyoutputs=yes",
//"-o", "preremoveoutputs=yes",
//"-w", "dupbuild=err",
//"-w", "outputdir=err",
//"-w", "missingoutfile=err",
"-v",
"-j", strconv.Itoa(config.Parallel()),
//"--frontend-file", fifo,
"--log_dir", config.SoongOutDir(),
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
}
default:
// NINJA_NINJA is the default.
ninjaCmd = config.NinjaBin()
ninjaArgs = []string{
"-d", "keepdepfile",
"-d", "stats",
"-o", "usesphonyoutputs=yes",
"-o", "preremoveoutputs=yes",
"-w", "dupbuild=err",
"-w", "outputdir=err",
"-w", "missingoutfile=err",
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
}
} }
if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok { if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
@@ -623,10 +648,6 @@ func runSoong(ctx Context, config Config) {
} }
ninjaArgs = append(ninjaArgs, targets...) ninjaArgs = append(ninjaArgs, targets...)
ninjaCmd := config.NinjaBin()
if config.useN2 {
ninjaCmd = config.N2Bin()
}
cmd := Command(ctx, config, "soong bootstrap", cmd := Command(ctx, config, "soong bootstrap",
ninjaCmd, ninjaArgs...) ninjaCmd, ninjaArgs...)