1// Copyright 2017 Google Inc. All rights reserved. 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 cc 16 17import ( 18 "errors" 19 "sort" 20 "strings" 21 "sync" 22 23 "android/soong/android" 24 "android/soong/cc/config" 25) 26 27type VndkProperties struct { 28 Vndk struct { 29 // declared as a VNDK or VNDK-SP module. The vendor variant 30 // will be installed in /system instead of /vendor partition. 31 // 32 // `vendor_vailable` must be explicitly set to either true or 33 // false together with `vndk: {enabled: true}`. 34 Enabled *bool 35 36 // declared as a VNDK-SP module, which is a subset of VNDK. 37 // 38 // `vndk: { enabled: true }` must set together. 39 // 40 // All these modules are allowed to link to VNDK-SP or LL-NDK 41 // modules only. Other dependency will cause link-type errors. 42 // 43 // If `support_system_process` is not set or set to false, 44 // the module is VNDK-core and can link to other VNDK-core, 45 // VNDK-SP or LL-NDK modules only. 46 Support_system_process *bool 47 48 // Extending another module 49 Extends *string 50 } 51} 52 53type vndkdep struct { 54 Properties VndkProperties 55} 56 57func (vndk *vndkdep) props() []interface{} { 58 return []interface{}{&vndk.Properties} 59} 60 61func (vndk *vndkdep) begin(ctx BaseModuleContext) {} 62 63func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps { 64 return deps 65} 66 67func (vndk *vndkdep) isVndk() bool { 68 return Bool(vndk.Properties.Vndk.Enabled) 69} 70 71func (vndk *vndkdep) isVndkSp() bool { 72 return Bool(vndk.Properties.Vndk.Support_system_process) 73} 74 75func (vndk *vndkdep) isVndkExt() bool { 76 return vndk.Properties.Vndk.Extends != nil 77} 78 79func (vndk *vndkdep) getVndkExtendsModuleName() string { 80 return String(vndk.Properties.Vndk.Extends) 81} 82 83func (vndk *vndkdep) typeName() string { 84 if !vndk.isVndk() { 85 return "native:vendor" 86 } 87 if !vndk.isVndkExt() { 88 if !vndk.isVndkSp() { 89 return "native:vendor:vndk" 90 } 91 return "native:vendor:vndksp" 92 } 93 if !vndk.isVndkSp() { 94 return "native:vendor:vndkext" 95 } 96 return "native:vendor:vndkspext" 97} 98 99func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag dependencyTag) { 100 if to.linker == nil { 101 return 102 } 103 if !vndk.isVndk() { 104 // Non-VNDK modules (those installed to /vendor) can't depend on modules marked with 105 // vendor_available: false. 106 violation := false 107 if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) { 108 violation = true 109 } else { 110 if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) { 111 // Vendor_available == nil && !Bool(Vendor_available) should be okay since 112 // it means a vendor-only library which is a valid dependency for non-VNDK 113 // modules. 114 violation = true 115 } 116 } 117 if violation { 118 ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name()) 119 } 120 } 121 if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() { 122 // Check only shared libraries. 123 // Other (static and LL-NDK) libraries are allowed to link. 124 return 125 } 126 if !to.Properties.UseVndk { 127 ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library", 128 vndk.typeName(), to.Name()) 129 return 130 } 131 if tag == vndkExtDepTag { 132 // Ensure `extends: "name"` property refers a vndk module that has vendor_available 133 // and has identical vndk properties. 134 if to.vndkdep == nil || !to.vndkdep.isVndk() { 135 ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name()) 136 return 137 } 138 if vndk.isVndkSp() != to.vndkdep.isVndkSp() { 139 ctx.ModuleErrorf( 140 "`extends` refers a module %q with mismatched support_system_process", 141 to.Name()) 142 return 143 } 144 if !Bool(to.VendorProperties.Vendor_available) { 145 ctx.ModuleErrorf( 146 "`extends` refers module %q which does not have `vendor_available: true`", 147 to.Name()) 148 return 149 } 150 } 151 if to.vndkdep == nil { 152 return 153 } 154 155 // Check the dependencies of VNDK shared libraries. 156 if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil { 157 ctx.ModuleErrorf("(%s) should not link to %q (%s): %v", 158 vndk.typeName(), to.Name(), to.vndkdep.typeName(), err) 159 return 160 } 161} 162 163func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error { 164 // Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules. 165 if from.isVndkExt() { 166 if from.isVndkSp() { 167 if to.isVndk() && !to.isVndkSp() { 168 return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions") 169 } 170 return nil 171 } 172 // VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. 173 return nil 174 } 175 if from.isVndk() { 176 if to.isVndkExt() { 177 return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions") 178 } 179 if from.isVndkSp() { 180 if !to.isVndkSp() { 181 return errors.New("VNDK-SP must only depend on VNDK-SP") 182 } 183 return nil 184 } 185 if !to.isVndk() { 186 return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP") 187 } 188 return nil 189 } 190 // Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. 191 return nil 192} 193 194var ( 195 vndkCoreLibraries []string 196 vndkSpLibraries []string 197 llndkLibraries []string 198 vndkPrivateLibraries []string 199 vndkUsingCoreVariantLibraries []string 200 vndkLibrariesLock sync.Mutex 201) 202 203// gather list of vndk-core, vndk-sp, and ll-ndk libs 204func VndkMutator(mctx android.BottomUpMutatorContext) { 205 if m, ok := mctx.Module().(*Module); ok && m.Enabled() { 206 if lib, ok := m.linker.(*llndkStubDecorator); ok { 207 vndkLibrariesLock.Lock() 208 defer vndkLibrariesLock.Unlock() 209 name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix) 210 if !inList(name, llndkLibraries) { 211 llndkLibraries = append(llndkLibraries, name) 212 sort.Strings(llndkLibraries) 213 } 214 if !Bool(lib.Properties.Vendor_available) { 215 if !inList(name, vndkPrivateLibraries) { 216 vndkPrivateLibraries = append(vndkPrivateLibraries, name) 217 sort.Strings(vndkPrivateLibraries) 218 } 219 } 220 } else { 221 lib, is_lib := m.linker.(*libraryDecorator) 222 prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker) 223 if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) { 224 name := strings.TrimPrefix(m.Name(), "prebuilt_") 225 if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { 226 vndkLibrariesLock.Lock() 227 defer vndkLibrariesLock.Unlock() 228 if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) { 229 if !inList(name, vndkUsingCoreVariantLibraries) { 230 vndkUsingCoreVariantLibraries = append(vndkUsingCoreVariantLibraries, name) 231 sort.Strings(vndkUsingCoreVariantLibraries) 232 } 233 } 234 if m.vndkdep.isVndkSp() { 235 if !inList(name, vndkSpLibraries) { 236 vndkSpLibraries = append(vndkSpLibraries, name) 237 sort.Strings(vndkSpLibraries) 238 } 239 } else { 240 if !inList(name, vndkCoreLibraries) { 241 vndkCoreLibraries = append(vndkCoreLibraries, name) 242 sort.Strings(vndkCoreLibraries) 243 } 244 } 245 if !Bool(m.VendorProperties.Vendor_available) { 246 if !inList(name, vndkPrivateLibraries) { 247 vndkPrivateLibraries = append(vndkPrivateLibraries, name) 248 sort.Strings(vndkPrivateLibraries) 249 } 250 } 251 } 252 } 253 } 254 } 255} 256