library_stub.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // Copyright 2021 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. package cc
  15. import (
  16. "regexp"
  17. "strings"
  18. "android/soong/android"
  19. "android/soong/multitree"
  20. )
  21. var (
  22. ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
  23. stubVariantRegex = regexp.MustCompile("apex\\.([a-zA-Z0-9]+)")
  24. )
  25. func init() {
  26. RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
  27. }
  28. func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
  29. ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
  30. ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
  31. ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
  32. }
  33. func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
  34. m, ok := ctx.Module().(*Module)
  35. if !ok {
  36. return
  37. }
  38. apiLibrary, ok := m.linker.(*apiLibraryDecorator)
  39. if !ok {
  40. return
  41. }
  42. if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
  43. // Add LLNDK variant dependency
  44. if inList("llndk", apiLibrary.properties.Variants) {
  45. variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
  46. ctx.AddDependency(m, nil, variantName)
  47. }
  48. } else if m.IsSdkVariant() {
  49. // Add NDK variant dependencies
  50. targetVariant := "ndk." + m.StubsVersion()
  51. if inList(targetVariant, apiLibrary.properties.Variants) {
  52. variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
  53. ctx.AddDependency(m, nil, variantName)
  54. }
  55. } else if m.IsStubs() {
  56. targetVariant := "apex." + m.StubsVersion()
  57. if inList(targetVariant, apiLibrary.properties.Variants) {
  58. variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
  59. ctx.AddDependency(m, nil, variantName)
  60. }
  61. }
  62. }
  63. // 'cc_api_library' is a module type which is from the exported API surface
  64. // with C shared library type. The module will replace original module, and
  65. // offer a link to the module that generates shared library object from the
  66. // map file.
  67. type apiLibraryProperties struct {
  68. Src *string `android:"arch_variant"`
  69. Variants []string
  70. }
  71. type apiLibraryDecorator struct {
  72. *libraryDecorator
  73. properties apiLibraryProperties
  74. }
  75. func CcApiLibraryFactory() android.Module {
  76. module, decorator := NewLibrary(android.DeviceSupported)
  77. apiLibraryDecorator := &apiLibraryDecorator{
  78. libraryDecorator: decorator,
  79. }
  80. apiLibraryDecorator.BuildOnlyShared()
  81. module.stl = nil
  82. module.sanitize = nil
  83. decorator.disableStripping()
  84. module.compiler = nil
  85. module.linker = apiLibraryDecorator
  86. module.installer = nil
  87. module.library = apiLibraryDecorator
  88. module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
  89. // Prevent default system libs (libc, libm, and libdl) from being linked
  90. if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
  91. apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
  92. }
  93. apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
  94. apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
  95. module.Init()
  96. return module
  97. }
  98. func (d *apiLibraryDecorator) Name(basename string) string {
  99. return basename + multitree.GetApiImportSuffix()
  100. }
  101. // Export include dirs without checking for existence.
  102. // The directories are not guaranteed to exist during Soong analysis.
  103. func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
  104. exporterProps := d.flagExporter.Properties
  105. for _, dir := range exporterProps.Export_include_dirs {
  106. d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
  107. }
  108. // system headers
  109. for _, dir := range exporterProps.Export_system_include_dirs {
  110. d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
  111. }
  112. }
  113. func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
  114. d.baseLinker.linkerInit(ctx)
  115. if d.hasNDKStubs() {
  116. // Set SDK version of module as current
  117. ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")
  118. // Add NDK stub as NDK known libs
  119. name := ctx.ModuleName()
  120. ndkKnownLibsLock.Lock()
  121. ndkKnownLibs := getNDKKnownLibs(ctx.Config())
  122. if !inList(name, *ndkKnownLibs) {
  123. *ndkKnownLibs = append(*ndkKnownLibs, name)
  124. }
  125. ndkKnownLibsLock.Unlock()
  126. }
  127. }
  128. func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
  129. m, _ := ctx.Module().(*Module)
  130. var in android.Path
  131. // src might not exist during the beginning of soong analysis in Multi-tree
  132. if src := String(d.properties.Src); src != "" {
  133. in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
  134. }
  135. libName := m.BaseModuleName() + multitree.GetApiImportSuffix()
  136. load_cc_variant := func(apiVariantModule string) {
  137. var mod android.Module
  138. ctx.VisitDirectDeps(func(depMod android.Module) {
  139. if depMod.Name() == apiVariantModule {
  140. mod = depMod
  141. libName = apiVariantModule
  142. }
  143. })
  144. if mod != nil {
  145. variantMod, ok := mod.(*CcApiVariant)
  146. if ok {
  147. in = variantMod.Src()
  148. // Copy LLDNK properties to cc_api_library module
  149. d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
  150. d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
  151. variantMod.exportProperties.Export_include_dirs...)
  152. // Export headers as system include dirs if specified. Mostly for libc
  153. if Bool(variantMod.exportProperties.Export_headers_as_system) {
  154. d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
  155. d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
  156. d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
  157. d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
  158. }
  159. }
  160. }
  161. }
  162. if m.UseVndk() && d.hasLLNDKStubs() {
  163. // LLNDK variant
  164. load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "llndk", ""))
  165. } else if m.IsSdkVariant() {
  166. // NDK Variant
  167. load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion()))
  168. } else if m.IsStubs() {
  169. // APEX Variant
  170. load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "apex", m.StubsVersion()))
  171. }
  172. // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
  173. d.exportIncludes(ctx)
  174. d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
  175. d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
  176. d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
  177. d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
  178. d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
  179. if in == nil {
  180. ctx.PropertyErrorf("src", "Unable to locate source property")
  181. return nil
  182. }
  183. // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
  184. // The .so file itself has an order-only dependency on the headers contributed by this library.
  185. // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
  186. d.libraryDecorator.reexportDeps(in)
  187. d.libraryDecorator.flagExporter.setProvider(ctx)
  188. d.unstrippedOutputFile = in
  189. libName += flags.Toolchain.ShlibSuffix()
  190. tocFile := android.PathForModuleOut(ctx, libName+".toc")
  191. d.tocFile = android.OptionalPathForPath(tocFile)
  192. TransformSharedObjectToToc(ctx, in, tocFile)
  193. outputFile := android.PathForModuleOut(ctx, libName)
  194. // TODO(b/270485584) This copies with a new name, just to avoid conflict with prebuilts.
  195. // We can just use original input if there is any way to avoid name conflict without copy.
  196. ctx.Build(pctx, android.BuildParams{
  197. Rule: android.Cp,
  198. Description: "API surface imported library",
  199. Input: in,
  200. Output: outputFile,
  201. Args: map[string]string{
  202. "cpFlags": "-L",
  203. },
  204. })
  205. ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
  206. SharedLibrary: outputFile,
  207. Target: ctx.Target(),
  208. TableOfContents: d.tocFile,
  209. })
  210. d.shareStubs(ctx)
  211. return outputFile
  212. }
  213. // Share additional information about stub libraries with provider
  214. func (d *apiLibraryDecorator) shareStubs(ctx ModuleContext) {
  215. stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
  216. if len(stubs) > 0 {
  217. var stubsInfo []SharedStubLibrary
  218. for _, stub := range stubs {
  219. stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
  220. flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
  221. stubsInfo = append(stubsInfo, SharedStubLibrary{
  222. Version: moduleLibraryInterface(stub).stubsVersion(),
  223. SharedLibraryInfo: stubInfo,
  224. FlagExporterInfo: flagInfo,
  225. })
  226. }
  227. ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
  228. SharedStubLibraries: stubsInfo,
  229. IsLLNDK: ctx.IsLlndk(),
  230. })
  231. }
  232. }
  233. func (d *apiLibraryDecorator) availableFor(what string) bool {
  234. // Stub from API surface should be available for any APEX.
  235. return true
  236. }
  237. func (d *apiLibraryDecorator) hasApexStubs() bool {
  238. for _, variant := range d.properties.Variants {
  239. if strings.HasPrefix(variant, "apex") {
  240. return true
  241. }
  242. }
  243. return false
  244. }
  245. func (d *apiLibraryDecorator) hasStubsVariants() bool {
  246. return d.hasApexStubs()
  247. }
  248. func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
  249. m, ok := ctx.Module().(*Module)
  250. if !ok {
  251. return nil
  252. }
  253. // TODO(b/244244438) Create more version information for NDK and APEX variations
  254. // NDK variants
  255. if m.IsSdkVariant() {
  256. // TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
  257. if d.hasNDKStubs() {
  258. return d.getNdkVersions()
  259. }
  260. }
  261. if d.hasLLNDKStubs() && m.UseVndk() {
  262. // LLNDK libraries only need a single stubs variant.
  263. return []string{android.FutureApiLevel.String()}
  264. }
  265. stubsVersions := d.getStubVersions()
  266. if len(stubsVersions) != 0 {
  267. return stubsVersions
  268. }
  269. if m.MinSdkVersion() == "" {
  270. return nil
  271. }
  272. firstVersion, err := nativeApiLevelFromUser(ctx,
  273. m.MinSdkVersion())
  274. if err != nil {
  275. return nil
  276. }
  277. return ndkLibraryVersions(ctx, firstVersion)
  278. }
  279. func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
  280. return inList("llndk", d.properties.Variants)
  281. }
  282. func (d *apiLibraryDecorator) hasNDKStubs() bool {
  283. for _, variant := range d.properties.Variants {
  284. if ndkVariantRegex.MatchString(variant) {
  285. return true
  286. }
  287. }
  288. return false
  289. }
  290. func (d *apiLibraryDecorator) getNdkVersions() []string {
  291. ndkVersions := []string{}
  292. for _, variant := range d.properties.Variants {
  293. if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
  294. ndkVersions = append(ndkVersions, match[1])
  295. }
  296. }
  297. return ndkVersions
  298. }
  299. func (d *apiLibraryDecorator) getStubVersions() []string {
  300. stubVersions := []string{}
  301. for _, variant := range d.properties.Variants {
  302. if match := stubVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
  303. stubVersions = append(stubVersions, match[1])
  304. }
  305. }
  306. return stubVersions
  307. }
  308. // 'cc_api_headers' is similar with 'cc_api_library', but which replaces
  309. // header libraries. The module will replace any dependencies to existing
  310. // original header libraries.
  311. type apiHeadersDecorator struct {
  312. *libraryDecorator
  313. }
  314. func CcApiHeadersFactory() android.Module {
  315. module, decorator := NewLibrary(android.DeviceSupported)
  316. apiHeadersDecorator := &apiHeadersDecorator{
  317. libraryDecorator: decorator,
  318. }
  319. apiHeadersDecorator.HeaderOnly()
  320. module.stl = nil
  321. module.sanitize = nil
  322. decorator.disableStripping()
  323. module.compiler = nil
  324. module.linker = apiHeadersDecorator
  325. module.installer = nil
  326. // Prevent default system libs (libc, libm, and libdl) from being linked
  327. if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
  328. apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
  329. }
  330. apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
  331. apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
  332. module.Init()
  333. return module
  334. }
  335. func (d *apiHeadersDecorator) Name(basename string) string {
  336. return basename + multitree.GetApiImportSuffix()
  337. }
  338. func (d *apiHeadersDecorator) availableFor(what string) bool {
  339. // Stub from API surface should be available for any APEX.
  340. return true
  341. }
  342. type ccApiexportProperties struct {
  343. Src *string `android:"arch_variant"`
  344. Variant *string
  345. Version *string
  346. }
  347. type variantExporterProperties struct {
  348. // Header directory to export
  349. Export_include_dirs []string `android:"arch_variant"`
  350. // Export all headers as system include
  351. Export_headers_as_system *bool
  352. }
  353. type CcApiVariant struct {
  354. android.ModuleBase
  355. properties ccApiexportProperties
  356. exportProperties variantExporterProperties
  357. src android.Path
  358. }
  359. var _ android.Module = (*CcApiVariant)(nil)
  360. var _ android.ImageInterface = (*CcApiVariant)(nil)
  361. func CcApiVariantFactory() android.Module {
  362. module := &CcApiVariant{}
  363. module.AddProperties(&module.properties)
  364. module.AddProperties(&module.exportProperties)
  365. android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
  366. return module
  367. }
  368. func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  369. // No need to build
  370. if String(v.properties.Src) == "" {
  371. ctx.PropertyErrorf("src", "src is a required property")
  372. }
  373. // Skip the existence check of the stub prebuilt file.
  374. // The file is not guaranteed to exist during Soong analysis.
  375. // Build orchestrator will be responsible for creating a connected ninja graph.
  376. v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), String(v.properties.Src))
  377. }
  378. func (v *CcApiVariant) Name() string {
  379. version := String(v.properties.Version)
  380. return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
  381. }
  382. func (v *CcApiVariant) Src() android.Path {
  383. return v.src
  384. }
  385. func BuildApiVariantName(baseName string, variant string, version string) string {
  386. names := []string{baseName, variant}
  387. if version != "" {
  388. names = append(names, version)
  389. }
  390. return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
  391. }
  392. // Implement ImageInterface to generate image variants
  393. func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
  394. func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
  395. return inList(String(v.properties.Variant), []string{"ndk", "apex"})
  396. }
  397. func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
  398. func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
  399. func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
  400. func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
  401. func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
  402. var variations []string
  403. platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
  404. if String(v.properties.Variant) == "llndk" {
  405. variations = append(variations, VendorVariationPrefix+platformVndkVersion)
  406. variations = append(variations, ProductVariationPrefix+platformVndkVersion)
  407. }
  408. return variations
  409. }
  410. func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
  411. }