1// Copyright (C) 2021 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package filesystem 16 17import ( 18 "android/soong/android" 19 "android/soong/linkerconfig" 20) 21 22type systemImage struct { 23 filesystem 24 25 properties systemImageProperties 26} 27 28type systemImageProperties struct { 29 // Path to the input linker config json file. 30 Linker_config_src *string 31} 32 33// android_system_image is a specialization of android_filesystem for the 'system' partition. 34// Currently, the only difference is the inclusion of linker.config.pb file which specifies 35// the provided and the required libraries to and from APEXes. 36func systemImageFactory() android.Module { 37 module := &systemImage{} 38 module.AddProperties(&module.properties) 39 module.filesystem.buildExtraFiles = module.buildExtraFiles 40 module.filesystem.filterPackagingSpec = module.filterPackagingSpec 41 initFilesystemModule(&module.filesystem) 42 return module 43} 44 45func (s *systemImage) buildExtraFiles(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths { 46 if s.filesystem.properties.Partition_type != nil { 47 ctx.PropertyErrorf("partition_type", "partition_type must be unset on an android_system_image module. It is assumed to be 'system'.") 48 } 49 lc := s.buildLinkerConfigFile(ctx, root) 50 // Add more files if needed 51 return []android.OutputPath{lc} 52} 53 54func (s *systemImage) buildLinkerConfigFile(ctx android.ModuleContext, root android.OutputPath) android.OutputPath { 55 input := android.PathForModuleSrc(ctx, android.String(s.properties.Linker_config_src)) 56 output := root.Join(ctx, "system", "etc", "linker.config.pb") 57 58 // we need "Module"s for packaging items 59 modulesInPackageByModule := make(map[android.Module]bool) 60 modulesInPackageByName := make(map[string]bool) 61 62 deps := s.gatherFilteredPackagingSpecs(ctx) 63 ctx.WalkDeps(func(child, parent android.Module) bool { 64 for _, ps := range child.PackagingSpecs() { 65 if _, ok := deps[ps.RelPathInPackage()]; ok { 66 modulesInPackageByModule[child] = true 67 modulesInPackageByName[child.Name()] = true 68 return true 69 } 70 } 71 return true 72 }) 73 74 provideModules := make([]android.Module, 0, len(modulesInPackageByModule)) 75 for mod := range modulesInPackageByModule { 76 provideModules = append(provideModules, mod) 77 } 78 79 var requireModules []android.Module 80 ctx.WalkDeps(func(child, parent android.Module) bool { 81 _, parentInPackage := modulesInPackageByModule[parent] 82 _, childInPackageName := modulesInPackageByName[child.Name()] 83 84 // When parent is in the package, and child (or its variant) is not, this can be from an interface. 85 if parentInPackage && !childInPackageName { 86 requireModules = append(requireModules, child) 87 } 88 return true 89 }) 90 91 builder := android.NewRuleBuilder(pctx, ctx) 92 linkerconfig.BuildLinkerConfig(ctx, builder, input, provideModules, requireModules, output) 93 builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) 94 return output 95} 96 97// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" partition. 98// Note that "apex" module installs its contents to "apex"(fake partition) as well 99// for symbol lookup by imitating "activated" paths. 100func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool { 101 return s.filesystem.filterInstallablePackagingSpec(ps) && ps.Partition() == "system" 102} 103