Merge "android_system_image that generates linker.config.pb"
This commit is contained in:
commit
08bd0dd8c5
7 changed files with 192 additions and 21 deletions
|
@ -30,7 +30,7 @@ type stubLibraries struct {
|
|||
}
|
||||
|
||||
// Check if the module defines stub, or itself is stub
|
||||
func isStubTarget(m *Module) bool {
|
||||
func IsStubTarget(m *Module) bool {
|
||||
if m.IsStubs() || m.HasStubsVariants() {
|
||||
return true
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func (s *stubLibraries) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
// Visit all generated soong modules and store stub library file names.
|
||||
ctx.VisitAllModules(func(module android.Module) {
|
||||
if m, ok := module.(*Module); ok {
|
||||
if isStubTarget(m) {
|
||||
if IsStubTarget(m) {
|
||||
if name := getInstalledFileName(m); name != "" {
|
||||
s.stubLibraryMap[name] = true
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@ bootstrap_go_package {
|
|||
"blueprint",
|
||||
"soong",
|
||||
"soong-android",
|
||||
"soong-linkerconfig",
|
||||
],
|
||||
srcs: [
|
||||
"bootimg.go",
|
||||
"filesystem.go",
|
||||
"logical_partition.go",
|
||||
"system_image.go",
|
||||
"vbmeta.go",
|
||||
"testing.go",
|
||||
],
|
||||
|
|
|
@ -31,6 +31,7 @@ func init() {
|
|||
|
||||
func registerBuildComponents(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("android_filesystem", filesystemFactory)
|
||||
ctx.RegisterModuleType("android_system_image", systemImageFactory)
|
||||
}
|
||||
|
||||
type filesystem struct {
|
||||
|
@ -39,6 +40,9 @@ type filesystem struct {
|
|||
|
||||
properties filesystemProperties
|
||||
|
||||
// Function that builds extra files under the root directory and returns the files
|
||||
buildExtraFiles func(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths
|
||||
|
||||
output android.OutputPath
|
||||
installDir android.InstallPath
|
||||
}
|
||||
|
@ -87,10 +91,14 @@ type filesystemProperties struct {
|
|||
// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory.
|
||||
func filesystemFactory() android.Module {
|
||||
module := &filesystem{}
|
||||
initFilesystemModule(module)
|
||||
return module
|
||||
}
|
||||
|
||||
func initFilesystemModule(module *filesystem) {
|
||||
module.AddProperties(&module.properties)
|
||||
android.InitPackageModule(module)
|
||||
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
||||
return module
|
||||
}
|
||||
|
||||
var dependencyTag = struct {
|
||||
|
@ -148,7 +156,7 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
ctx.InstallFile(f.installDir, f.installFileName(), f.output)
|
||||
}
|
||||
|
||||
// root zip will contain stuffs like dirs or symlinks.
|
||||
// root zip will contain extra files/dirs that are not from the `deps` property.
|
||||
func (f *filesystem) buildRootZip(ctx android.ModuleContext) android.OutputPath {
|
||||
rootDir := android.PathForModuleGen(ctx, "root").OutputPath
|
||||
builder := android.NewRuleBuilder(pctx, ctx)
|
||||
|
@ -182,15 +190,34 @@ func (f *filesystem) buildRootZip(ctx android.ModuleContext) android.OutputPath
|
|||
builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String())
|
||||
}
|
||||
|
||||
zipOut := android.PathForModuleGen(ctx, "root.zip").OutputPath
|
||||
// create extra files if there's any
|
||||
rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath
|
||||
var extraFiles android.OutputPaths
|
||||
if f.buildExtraFiles != nil {
|
||||
extraFiles = f.buildExtraFiles(ctx, rootForExtraFiles)
|
||||
for _, f := range extraFiles {
|
||||
rel, _ := filepath.Rel(rootForExtraFiles.String(), f.String())
|
||||
if strings.HasPrefix(rel, "..") {
|
||||
panic(fmt.Errorf("%q is not under %q\n", f, rootForExtraFiles))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.Command().
|
||||
BuiltTool("soong_zip").
|
||||
FlagWithOutput("-o ", zipOut).
|
||||
// Zip them all
|
||||
zipOut := android.PathForModuleGen(ctx, "root.zip").OutputPath
|
||||
zipCommand := builder.Command().BuiltTool("soong_zip")
|
||||
zipCommand.FlagWithOutput("-o ", zipOut).
|
||||
FlagWithArg("-C ", rootDir.String()).
|
||||
Flag("-L 0"). // no compression because this will be unzipped soon
|
||||
FlagWithArg("-D ", rootDir.String()).
|
||||
Flag("-d") // include empty directories
|
||||
if len(extraFiles) > 0 {
|
||||
zipCommand.FlagWithArg("-C ", rootForExtraFiles.String())
|
||||
for _, f := range extraFiles {
|
||||
zipCommand.FlagWithInput("-f ", f)
|
||||
}
|
||||
}
|
||||
|
||||
builder.Command().Text("rm -rf").Text(rootDir.String())
|
||||
|
||||
builder.Build("zip_root", fmt.Sprintf("zipping root contents for %s", ctx.ModuleName()))
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -27,6 +28,7 @@ func TestMain(m *testing.M) {
|
|||
|
||||
var fixture = android.GroupFixturePreparers(
|
||||
android.PrepareForIntegrationTestWithAndroid,
|
||||
cc.PrepareForIntegrationTestWithCc,
|
||||
PrepareForTestWithFilesystemBuildComponents,
|
||||
)
|
||||
|
||||
|
@ -40,3 +42,35 @@ func TestFileSystemDeps(t *testing.T) {
|
|||
// produces "myfilesystem.img"
|
||||
result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img")
|
||||
}
|
||||
|
||||
func TestFileSystemFillsLinkerConfigWithStubLibs(t *testing.T) {
|
||||
result := fixture.RunTestWithBp(t, `
|
||||
android_system_image {
|
||||
name: "myfilesystem",
|
||||
deps: [
|
||||
"libfoo",
|
||||
"libbar",
|
||||
],
|
||||
linker_config_src: "linker.config.json",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stubs: {
|
||||
symbol_file: "libfoo.map.txt",
|
||||
},
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
}
|
||||
`)
|
||||
|
||||
module := result.ModuleForTests("myfilesystem", "android_common")
|
||||
output := module.Output("system/etc/linker.config.pb")
|
||||
|
||||
android.AssertStringDoesContain(t, "linker.config.pb should have libfoo",
|
||||
output.RuleParams.Command, "libfoo.so")
|
||||
android.AssertStringDoesNotContain(t, "linker.config.pb should not have libbar",
|
||||
output.RuleParams.Command, "libbar.so")
|
||||
}
|
||||
|
|
68
filesystem/system_image.go
Normal file
68
filesystem/system_image.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright (C) 2021 The Android Open Source Project
|
||||
//
|
||||
// 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 filesystem
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"android/soong/linkerconfig"
|
||||
)
|
||||
|
||||
type systemImage struct {
|
||||
filesystem
|
||||
|
||||
properties systemImageProperties
|
||||
}
|
||||
|
||||
type systemImageProperties struct {
|
||||
// Path to the input linker config json file.
|
||||
Linker_config_src *string
|
||||
}
|
||||
|
||||
// android_system_image is a specialization of android_filesystem for the 'system' partition.
|
||||
// Currently, the only difference is the inclusion of linker.config.pb file which specifies
|
||||
// the provided and the required libraries to and from APEXes.
|
||||
func systemImageFactory() android.Module {
|
||||
module := &systemImage{}
|
||||
module.AddProperties(&module.properties)
|
||||
module.filesystem.buildExtraFiles = module.buildExtraFiles
|
||||
initFilesystemModule(&module.filesystem)
|
||||
return module
|
||||
}
|
||||
|
||||
func (s *systemImage) buildExtraFiles(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths {
|
||||
lc := s.buildLinkerConfigFile(ctx, root)
|
||||
// Add more files if needed
|
||||
return []android.OutputPath{lc}
|
||||
}
|
||||
|
||||
func (s *systemImage) buildLinkerConfigFile(ctx android.ModuleContext, root android.OutputPath) android.OutputPath {
|
||||
input := android.PathForModuleSrc(ctx, android.String(s.properties.Linker_config_src))
|
||||
output := root.Join(ctx, "system", "etc", "linker.config.pb")
|
||||
var otherModules []android.Module
|
||||
ctx.WalkDeps(func(child, parent android.Module) bool {
|
||||
// Don't track direct dependencies that aren't not packaged
|
||||
if parent == s {
|
||||
if pi, ok := ctx.OtherModuleDependencyTag(child).(android.PackagingItem); !ok || !pi.IsPackagingItem() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
otherModules = append(otherModules, child)
|
||||
return true
|
||||
})
|
||||
builder := android.NewRuleBuilder(pctx, ctx)
|
||||
linkerconfig.BuildLinkerConfig(ctx, builder, input, otherModules, output)
|
||||
builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
|
||||
return output
|
||||
}
|
|
@ -9,6 +9,7 @@ bootstrap_go_package {
|
|||
"blueprint",
|
||||
"soong",
|
||||
"soong-android",
|
||||
"soong-cc",
|
||||
"soong-etc",
|
||||
],
|
||||
srcs: [
|
||||
|
|
|
@ -15,11 +15,15 @@
|
|||
package linkerconfig
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"android/soong/etc"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/etc"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -81,24 +85,59 @@ func (l *linkerConfig) OutputFiles(tag string) (android.Paths, error) {
|
|||
}
|
||||
|
||||
func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
inputFile := android.PathForModuleSrc(ctx, android.String(l.properties.Src))
|
||||
l.outputFilePath = android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
|
||||
l.installDirPath = android.PathForModuleInstall(ctx, "etc")
|
||||
linkerConfigRule := android.NewRuleBuilder(pctx, ctx)
|
||||
linkerConfigRule.Command().
|
||||
BuiltTool("conv_linker_config").
|
||||
Flag("proto").
|
||||
FlagWithInput("-s ", inputFile).
|
||||
FlagWithOutput("-o ", l.outputFilePath)
|
||||
linkerConfigRule.Build("conv_linker_config",
|
||||
"Generate linker config protobuf "+l.outputFilePath.String())
|
||||
input := android.PathForModuleSrc(ctx, android.String(l.properties.Src))
|
||||
output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
|
||||
|
||||
builder := android.NewRuleBuilder(pctx, ctx)
|
||||
BuildLinkerConfig(ctx, builder, input, nil, output)
|
||||
builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
|
||||
|
||||
l.outputFilePath = output
|
||||
l.installDirPath = android.PathForModuleInstall(ctx, "etc")
|
||||
if !proptools.BoolDefault(l.properties.Installable, true) {
|
||||
l.SkipInstall()
|
||||
}
|
||||
ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
|
||||
}
|
||||
|
||||
func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
|
||||
input android.Path, otherModules []android.Module, output android.OutputPath) {
|
||||
|
||||
// First, convert the input json to protobuf format
|
||||
interimOutput := android.PathForModuleOut(ctx, "temp.pb")
|
||||
builder.Command().
|
||||
BuiltTool("conv_linker_config").
|
||||
Flag("proto").
|
||||
FlagWithInput("-s ", input).
|
||||
FlagWithOutput("-o ", interimOutput)
|
||||
|
||||
// Secondly, if there's provideLibs gathered from otherModules, append them
|
||||
var provideLibs []string
|
||||
for _, m := range otherModules {
|
||||
if c, ok := m.(*cc.Module); ok && cc.IsStubTarget(c) {
|
||||
for _, ps := range c.PackagingSpecs() {
|
||||
provideLibs = append(provideLibs, ps.FileName())
|
||||
}
|
||||
}
|
||||
}
|
||||
provideLibs = android.FirstUniqueStrings(provideLibs)
|
||||
sort.Strings(provideLibs)
|
||||
if len(provideLibs) > 0 {
|
||||
builder.Command().
|
||||
BuiltTool("conv_linker_config").
|
||||
Flag("append").
|
||||
FlagWithInput("-s ", interimOutput).
|
||||
FlagWithOutput("-o ", output).
|
||||
FlagWithArg("--key ", "provideLibs").
|
||||
FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " ")))
|
||||
} else {
|
||||
// If nothing to add, just cp to the final output
|
||||
builder.Command().Text("cp").Input(interimOutput).Output(output)
|
||||
}
|
||||
builder.Temporary(interimOutput)
|
||||
builder.DeleteTemporaryFiles()
|
||||
}
|
||||
|
||||
// linker_config generates protobuf file from json file. This protobuf file will be used from
|
||||
// linkerconfig while generating ld.config.txt. Format of this file can be found from
|
||||
// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
|
||||
|
|
Loading…
Reference in a new issue