Merge changes Ia67986af,I79da6b75
* changes: Mixed builds support for prebuilt_* targets Create GetPrebuiltFileInfo to Mixed builds cquery api
This commit is contained in:
@@ -187,6 +187,9 @@ type BazelContext interface {
|
||||
// Returns the results of the GetCcUnstrippedInfo query
|
||||
GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
|
||||
|
||||
// Returns the results of the GetPrebuiltFileInfo query
|
||||
GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error)
|
||||
|
||||
// ** end Cquery Results Retrieval Functions
|
||||
|
||||
// Issues commands to Bazel to receive results for all cquery requests
|
||||
@@ -272,11 +275,12 @@ var _ BazelContext = noopBazelContext{}
|
||||
type MockBazelContext struct {
|
||||
OutputBaseDir string
|
||||
|
||||
LabelToOutputFiles map[string][]string
|
||||
LabelToCcInfo map[string]cquery.CcInfo
|
||||
LabelToPythonBinary map[string]string
|
||||
LabelToApexInfo map[string]cquery.ApexInfo
|
||||
LabelToCcBinary map[string]cquery.CcUnstrippedInfo
|
||||
LabelToOutputFiles map[string][]string
|
||||
LabelToCcInfo map[string]cquery.CcInfo
|
||||
LabelToPythonBinary map[string]string
|
||||
LabelToApexInfo map[string]cquery.ApexInfo
|
||||
LabelToCcBinary map[string]cquery.CcUnstrippedInfo
|
||||
LabelToPrebuiltFileInfo map[string]cquery.PrebuiltFileInfo
|
||||
|
||||
BazelRequests map[string]bool
|
||||
}
|
||||
@@ -325,6 +329,14 @@ func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m MockBazelContext) GetPrebuiltFileInfo(label string, _ configKey) (cquery.PrebuiltFileInfo, error) {
|
||||
result, ok := m.LabelToPrebuiltFileInfo[label]
|
||||
if !ok {
|
||||
return cquery.PrebuiltFileInfo{}, fmt.Errorf("no target with label %q in LabelToPrebuiltFileInfo", label)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
@@ -433,6 +445,14 @@ func (bazelCtx *mixedBuildBazelContext) GetCcUnstrippedInfo(label string, cfgKey
|
||||
return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
|
||||
}
|
||||
|
||||
func (bazelCtx *mixedBuildBazelContext) GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error) {
|
||||
key := makeCqueryKey(label, cquery.GetPrebuiltFileInfo, cfgKey)
|
||||
if rawString, ok := bazelCtx.results[key]; ok {
|
||||
return cquery.GetPrebuiltFileInfo.ParseResult(strings.TrimSpace(rawString))
|
||||
}
|
||||
return cquery.PrebuiltFileInfo{}, fmt.Errorf("no bazel response for %s", key)
|
||||
}
|
||||
|
||||
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
@@ -454,6 +474,10 @@ func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcU
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (n noopBazelContext) GetPrebuiltFileInfo(_ string, _ configKey) (cquery.PrebuiltFileInfo, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ var (
|
||||
GetCcInfo = &getCcInfoType{}
|
||||
GetApexInfo = &getApexInfoType{}
|
||||
GetCcUnstrippedInfo = &getCcUnstrippedInfoType{}
|
||||
GetPrebuiltFileInfo = &getPrebuiltFileInfo{}
|
||||
)
|
||||
|
||||
type CcAndroidMkInfo struct {
|
||||
@@ -375,3 +376,51 @@ func parseJson(jsonString string, info interface{}) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type getPrebuiltFileInfo struct{}
|
||||
|
||||
// Name returns a string name for this request type. Such request type names must be unique,
|
||||
// and must only consist of alphanumeric characters.
|
||||
func (g getPrebuiltFileInfo) Name() string {
|
||||
return "getPrebuiltFileInfo"
|
||||
}
|
||||
|
||||
// StarlarkFunctionBody returns a starlark function body to process this request type.
|
||||
// The returned string is the body of a Starlark function which obtains
|
||||
// all request-relevant information about a target and returns a string containing
|
||||
// this information.
|
||||
// The function should have the following properties:
|
||||
// - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
|
||||
// - The return value must be a string.
|
||||
// - The function body should not be indented outside of its own scope.
|
||||
func (g getPrebuiltFileInfo) StarlarkFunctionBody() string {
|
||||
return `
|
||||
p = providers(target)
|
||||
prebuilt_file_info = p.get("//build/bazel/rules:prebuilt_file.bzl%PrebuiltFileInfo")
|
||||
if not prebuilt_file_info:
|
||||
fail("%s did not provide PrebuiltFileInfo" % id_string)
|
||||
|
||||
return json.encode({
|
||||
"Src": prebuilt_file_info.src.path,
|
||||
"Dir": prebuilt_file_info.dir,
|
||||
"Filename": prebuilt_file_info.filename,
|
||||
"Installable": prebuilt_file_info.installable,
|
||||
})`
|
||||
}
|
||||
|
||||
type PrebuiltFileInfo struct {
|
||||
// TODO: b/207489266 - Fully support all properties in prebuilt_file
|
||||
Src string
|
||||
Dir string
|
||||
Filename string
|
||||
Installable bool
|
||||
}
|
||||
|
||||
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
|
||||
// The given rawString must correspond to the string output which was created by evaluating the
|
||||
// Starlark given in StarlarkFunctionBody.
|
||||
func (g getPrebuiltFileInfo) ParseResult(rawString string) (PrebuiltFileInfo, error) {
|
||||
var info PrebuiltFileInfo
|
||||
err := parseJson(rawString, &info)
|
||||
return info, err
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ import (
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel"
|
||||
"android/soong/bazel/cquery"
|
||||
"android/soong/snapshot"
|
||||
)
|
||||
|
||||
@@ -329,7 +330,6 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
ctx.PropertyErrorf("src", "missing prebuilt source file")
|
||||
return
|
||||
}
|
||||
p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
|
||||
|
||||
if strings.Contains(filename, "/") {
|
||||
ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
|
||||
@@ -349,21 +349,42 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
}
|
||||
p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
|
||||
|
||||
// This ensures that outputFilePath has the correct name for others to
|
||||
// use, as the source file may have a different name.
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Cp,
|
||||
Output: p.outputFilePath,
|
||||
Input: p.sourceFilePath,
|
||||
})
|
||||
// Call InstallFile even when uninstallable to make the module included in the package
|
||||
ip := installProperties{
|
||||
installable: p.Installable(),
|
||||
filename: filename,
|
||||
sourceFilePath: p.sourceFilePath,
|
||||
symlinks: p.properties.Symlinks,
|
||||
}
|
||||
p.addInstallRules(ctx, ip)
|
||||
}
|
||||
|
||||
if !p.Installable() {
|
||||
type installProperties struct {
|
||||
installable bool
|
||||
filename string
|
||||
sourceFilePath android.Path
|
||||
symlinks []string
|
||||
}
|
||||
|
||||
// utility function to add install rules to the build graph.
|
||||
// Reduces code duplication between Soong and Mixed build analysis
|
||||
func (p *PrebuiltEtc) addInstallRules(ctx android.ModuleContext, ip installProperties) {
|
||||
if !ip.installable {
|
||||
p.SkipInstall()
|
||||
}
|
||||
|
||||
// Call InstallFile even when uninstallable to make the module included in the package
|
||||
installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
|
||||
for _, sl := range p.properties.Symlinks {
|
||||
// Copy the file from src to a location in out/ with the correct `filename`
|
||||
// This ensures that outputFilePath has the correct name for others to
|
||||
// use, as the source file may have a different name.
|
||||
p.outputFilePath = android.PathForModuleOut(ctx, ip.filename).OutputPath
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Cp,
|
||||
Output: p.outputFilePath,
|
||||
Input: ip.sourceFilePath,
|
||||
})
|
||||
|
||||
installPath := ctx.InstallFile(p.installDirPath, ip.filename, p.outputFilePath)
|
||||
for _, sl := range ip.symlinks {
|
||||
ctx.InstallSymlink(p.installDirPath, sl, installPath)
|
||||
}
|
||||
}
|
||||
@@ -781,3 +802,38 @@ func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext
|
||||
|
||||
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
|
||||
}
|
||||
|
||||
var _ android.MixedBuildBuildable = (*PrebuiltEtc)(nil)
|
||||
|
||||
func (pe *PrebuiltEtc) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (pe *PrebuiltEtc) QueueBazelCall(ctx android.BaseModuleContext) {
|
||||
ctx.Config().BazelContext.QueueBazelRequest(
|
||||
pe.GetBazelLabel(ctx, pe),
|
||||
cquery.GetPrebuiltFileInfo,
|
||||
android.GetConfigKey(ctx),
|
||||
)
|
||||
}
|
||||
|
||||
func (pe *PrebuiltEtc) ProcessBazelQueryResponse(ctx android.ModuleContext) {
|
||||
bazelCtx := ctx.Config().BazelContext
|
||||
pfi, err := bazelCtx.GetPrebuiltFileInfo(pe.GetBazelLabel(ctx, pe), android.GetConfigKey(ctx))
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Set properties for androidmk
|
||||
pe.installDirPath = android.PathForModuleInstall(ctx, pfi.Dir)
|
||||
|
||||
// Installation rules
|
||||
ip := installProperties{
|
||||
installable: pfi.Installable,
|
||||
filename: pfi.Filename,
|
||||
sourceFilePath: android.PathForSource(ctx, pfi.Src),
|
||||
// symlinks: pe.properties.Symlinks, // TODO: b/207489266 - Fully support all properties in prebuilt_file
|
||||
}
|
||||
pe.addInstallRules(ctx, ip)
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel/cquery"
|
||||
"android/soong/snapshot"
|
||||
)
|
||||
|
||||
@@ -494,3 +495,41 @@ func TestPrebuiltTakeSnapshot(t *testing.T) {
|
||||
checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrebuiltEtcAndroidMkEntriesWithBazel(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
prebuilt_etc {
|
||||
name: "myetc",
|
||||
src: "prebuilt_etc.rc", // filename in src tree
|
||||
filename: "init.rc", // target filename on device
|
||||
sub_dir: "subdir", // relative subdir for installation
|
||||
bazel_module: { label: "//foo/bar:myetc" },
|
||||
}
|
||||
`
|
||||
res := android.GroupFixturePreparers(
|
||||
prepareForPrebuiltEtcTest,
|
||||
android.FixtureModifyConfig(func(cfg android.Config) {
|
||||
cfg.BazelContext = android.MockBazelContext{
|
||||
LabelToPrebuiltFileInfo: map[string]cquery.PrebuiltFileInfo{
|
||||
"//foo/bar:myetc": cquery.PrebuiltFileInfo{
|
||||
Src: "foo/bar/prebuilt_etc.rc",
|
||||
Dir: "etc/subdir",
|
||||
Filename: "init.rc",
|
||||
Installable: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}),
|
||||
).RunTestWithBp(t, bp)
|
||||
ctx := res.ModuleForTests("myetc", "android_arm64_armv8-a")
|
||||
mod := ctx.Module()
|
||||
entries := android.AndroidMkEntriesForTest(t, res.TestContext, mod)[0]
|
||||
// verify androidmk entries
|
||||
android.AssertStringDoesContain(t, "LOCAL_MODULE_PATH should contain", entries.EntryMap["LOCAL_MODULE_PATH"][0], "etc/subdir")
|
||||
android.AssertStringEquals(t, "LOCAL_INSTALLED_MODULE_STEM is incorrect", "init.rc", entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
|
||||
// verify installation rules
|
||||
install := ctx.Description("install")
|
||||
android.AssertStringEquals(t, "Source location of prebuilt_etc installation", "out/soong/.intermediates/myetc/android_arm64_armv8-a/init.rc", install.Input.String())
|
||||
android.AssertStringEquals(t, "Target location of prebuilt_etc installation", "out/soong/target/product/test_device/system/etc/subdir/init.rc", install.Output.String())
|
||||
}
|
||||
|
Reference in New Issue
Block a user