diff --git a/cc/genrule.go b/cc/genrule.go index 9df52280e..239064f1c 100644 --- a/cc/genrule.go +++ b/cc/genrule.go @@ -15,6 +15,8 @@ package cc import ( + "fmt" + "android/soong/android" "android/soong/genrule" "android/soong/snapshot" @@ -36,13 +38,23 @@ type GenruleExtraProperties struct { // cc_genrule is a genrule that can depend on other cc_* objects. // The cmd may be run multiple times, once for each of the different arch/etc -// variations. +// variations. The following environment variables will be set when the command +// execute: +// +// CC_ARCH the name of the architecture the command is being executed for +// +// CC_MULTILIB "lib32" if the architecture the command is being executed for is 32-bit, +// "lib64" if it is 64-bit. +// +// CC_NATIVE_BRIDGE the name of the subdirectory that native bridge libraries are stored in if +// the architecture has native bridge enabled, empty if it is disabled. func GenRuleFactory() android.Module { module := genrule.NewGenRule() extra := &GenruleExtraProperties{} module.Extra = extra module.ImageInterface = extra + module.CmdModifier = genruleCmdModifier module.AddProperties(module.Extra) android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibBoth) @@ -53,6 +65,13 @@ func GenRuleFactory() android.Module { return module } +func genruleCmdModifier(ctx android.ModuleContext, cmd string) string { + target := ctx.Target() + arch := target.Arch.ArchType + return fmt.Sprintf("CC_ARCH=%s CC_NATIVE_BRIDGE=%s CC_MULTILIB=%s && %s", + arch.Name, target.NativeBridgeRelativePath, arch.Multilib, cmd) +} + var _ android.ImageInterface = (*GenruleExtraProperties)(nil) func (g *GenruleExtraProperties) ImageMutatorBegin(ctx android.BaseModuleContext) {} diff --git a/cc/genrule_test.go b/cc/genrule_test.go index b6afb05a7..f25f70416 100644 --- a/cc/genrule_test.go +++ b/cc/genrule_test.go @@ -115,3 +115,75 @@ func TestLibraryGenruleCmd(t *testing.T) { t.Errorf(`want inputs %v, got %v`, expected, got) } } + +func TestCmdPrefix(t *testing.T) { + bp := ` + cc_genrule { + name: "gen", + cmd: "echo foo", + out: ["out"], + native_bridge_supported: true, + } + ` + + testCases := []struct { + name string + variant string + preparer android.FixturePreparer + + arch string + nativeBridge string + multilib string + }{ + { + name: "arm", + variant: "android_arm_armv7-a-neon", + arch: "arm", + multilib: "lib32", + }, + { + name: "arm64", + variant: "android_arm64_armv8-a", + arch: "arm64", + multilib: "lib64", + }, + { + name: "nativebridge", + variant: "android_native_bridge_arm_armv7-a-neon", + preparer: android.FixtureModifyConfig(func(config android.Config) { + config.Targets[android.Android] = []android.Target{ + { + Os: android.Android, + Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, + NativeBridge: android.NativeBridgeDisabled, + }, + { + Os: android.Android, + Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, + NativeBridge: android.NativeBridgeEnabled, + NativeBridgeHostArchName: "x86", + NativeBridgeRelativePath: "arm", + }, + } + }), + arch: "arm", + multilib: "lib32", + nativeBridge: "arm", + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + result := android.GroupFixturePreparers( + PrepareForIntegrationTestWithCc, + android.OptionalFixturePreparer(tt.preparer), + ).RunTestWithBp(t, bp) + gen := result.ModuleForTests("gen", tt.variant) + sboxProto := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto")) + cmd := *sboxProto.Commands[0].Command + android.AssertStringDoesContain(t, "incorrect CC_ARCH", cmd, "CC_ARCH="+tt.arch+" ") + android.AssertStringDoesContain(t, "incorrect CC_NATIVE_BRIDGE", cmd, "CC_NATIVE_BRIDGE="+tt.nativeBridge+" ") + android.AssertStringDoesContain(t, "incorrect CC_MULTILIB", cmd, "CC_MULTILIB="+tt.multilib+" ") + }) + } +} diff --git a/genrule/genrule.go b/genrule/genrule.go index f4bde703a..96b610bac 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -156,6 +156,11 @@ type Module struct { // For other packages to make their own genrules with extra // properties Extra interface{} + + // CmdModifier can be set by wrappers around genrule to modify the command, for example to + // prefix environment variables to it. + CmdModifier func(ctx android.ModuleContext, cmd string) string + android.ImageInterface properties generatorProperties @@ -398,8 +403,13 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { var outputFiles android.WritablePaths var zipArgs strings.Builder + cmd := String(g.properties.Cmd) + if g.CmdModifier != nil { + cmd = g.CmdModifier(ctx, cmd) + } + // Generate tasks, either from genrule or gensrcs. - for _, task := range g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles) { + for _, task := range g.taskGenerator(ctx, cmd, srcFiles) { if len(task.out) == 0 { ctx.ModuleErrorf("must have at least one output file") return