1// Copyright 2016 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 17// The platform needs to provide the following artifacts for the NDK: 18// 1. Bionic headers. 19// 2. Platform API headers. 20// 3. NDK stub shared libraries. 21// 4. Bionic static libraries. 22// 23// TODO(danalbert): All of the above need to include NOTICE files. 24// 25// Components 1 and 2: Headers 26// The bionic and platform API headers are generalized into a single 27// `ndk_headers` rule. This rule has a `from` property that indicates a base 28// directory from which headers are to be taken, and a `to` property that 29// indicates where in the sysroot they should reside relative to usr/include. 30// There is also a `srcs` property that is glob compatible for specifying which 31// headers to include. 32// 33// Component 3: Stub Libraries 34// The shared libraries in the NDK are not the actual shared libraries they 35// refer to (to prevent people from accidentally loading them), but stub 36// libraries with placeholder implementations of everything for use at build time 37// only. 38// 39// Since we don't actually need to know anything about the stub libraries aside 40// from a list of functions and globals to be exposed, we can create these for 41// every platform level in the current tree. This is handled by the 42// ndk_library rule. 43// 44// Component 4: Static Libraries 45// The NDK only provides static libraries for bionic, not the platform APIs. 46// Since these need to be the actual implementation, we can't build old versions 47// in the current platform tree. As such, legacy versions are checked in 48// prebuilt to development/ndk, and a current version is built and archived as 49// part of the platform build. The platfrom already builds these libraries, our 50// NDK build rules only need to archive them for retrieval so they can be added 51// to the prebuilts. 52// 53// TODO(danalbert): Write `ndk_static_library` rule. 54 55import ( 56 "android/soong/android" 57) 58 59func init() { 60 android.RegisterModuleType("ndk_headers", ndkHeadersFactory) 61 android.RegisterModuleType("ndk_library", NdkLibraryFactory) 62 android.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) 63 android.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) 64 android.RegisterSingletonType("ndk", NdkSingleton) 65 66 pctx.Import("android/soong/android") 67} 68 69func getNdkInstallBase(ctx android.PathContext) android.InstallPath { 70 return android.PathForNdkInstall(ctx) 71} 72 73// Returns the main install directory for the NDK sysroot. Usable with --sysroot. 74func getNdkSysrootBase(ctx android.PathContext) android.InstallPath { 75 return getNdkInstallBase(ctx).Join(ctx, "sysroot") 76} 77 78// The base timestamp file depends on the NDK headers and stub shared libraries, 79// but not the static libraries. This distinction is needed because the static 80// libraries themselves might need to depend on the base sysroot. 81func getNdkBaseTimestampFile(ctx android.PathContext) android.WritablePath { 82 return android.PathForOutput(ctx, "ndk_base.timestamp") 83} 84 85// The headers timestamp file depends only on the NDK headers. 86// This is used mainly for .tidy files that do not need any stub libraries. 87func getNdkHeadersTimestampFile(ctx android.PathContext) android.WritablePath { 88 return android.PathForOutput(ctx, "ndk_headers.timestamp") 89} 90 91// The full timestamp file depends on the base timestamp *and* the static 92// libraries. 93func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath { 94 return android.PathForOutput(ctx, "ndk.timestamp") 95} 96 97func NdkSingleton() android.Singleton { 98 return &ndkSingleton{} 99} 100 101type ndkSingleton struct{} 102 103func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { 104 var staticLibInstallPaths android.Paths 105 var headerPaths android.Paths 106 var installPaths android.Paths 107 var licensePaths android.Paths 108 ctx.VisitAllModules(func(module android.Module) { 109 if m, ok := module.(android.Module); ok && !m.Enabled() { 110 return 111 } 112 113 if m, ok := module.(*headerModule); ok { 114 headerPaths = append(headerPaths, m.installPaths...) 115 installPaths = append(installPaths, m.installPaths...) 116 licensePaths = append(licensePaths, m.licensePath) 117 } 118 119 if m, ok := module.(*versionedHeaderModule); ok { 120 headerPaths = append(headerPaths, m.installPaths...) 121 installPaths = append(installPaths, m.installPaths...) 122 licensePaths = append(licensePaths, m.licensePath) 123 } 124 125 if m, ok := module.(*preprocessedHeadersModule); ok { 126 headerPaths = append(headerPaths, m.installPaths...) 127 installPaths = append(installPaths, m.installPaths...) 128 licensePaths = append(licensePaths, m.licensePath) 129 } 130 131 if m, ok := module.(*Module); ok { 132 if installer, ok := m.installer.(*stubDecorator); ok && m.library.buildStubs() { 133 installPaths = append(installPaths, installer.installPath) 134 } 135 136 if library, ok := m.linker.(*libraryDecorator); ok { 137 if library.ndkSysrootPath != nil { 138 staticLibInstallPaths = append( 139 staticLibInstallPaths, library.ndkSysrootPath) 140 } 141 } 142 } 143 }) 144 145 // Include only a single copy of each license file. The Bionic NOTICE is 146 // long and is referenced by multiple Bionic modules. 147 licensePaths = android.FirstUniquePaths(licensePaths) 148 149 combinedLicense := getNdkInstallBase(ctx).Join(ctx, "NOTICE") 150 ctx.Build(pctx, android.BuildParams{ 151 Rule: android.Cat, 152 Description: "combine licenses", 153 Output: combinedLicense, 154 Inputs: licensePaths, 155 }) 156 157 baseDepPaths := append(installPaths, combinedLicense) 158 159 ctx.Build(pctx, android.BuildParams{ 160 Rule: android.Touch, 161 Output: getNdkBaseTimestampFile(ctx), 162 Implicits: baseDepPaths, 163 Validation: getNdkAbiDiffTimestampFile(ctx), 164 }) 165 166 ctx.Build(pctx, android.BuildParams{ 167 Rule: android.Touch, 168 Output: getNdkHeadersTimestampFile(ctx), 169 Implicits: headerPaths, 170 }) 171 172 fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx)) 173 174 // There's a phony "ndk" rule defined in core/main.mk that depends on this. 175 // `m ndk` will build the sysroots for the architectures in the current 176 // lunch target. `build/soong/scripts/build-ndk-prebuilts.sh` will build the 177 // sysroots for all the NDK architectures and package them so they can be 178 // imported into the NDK's build. 179 ctx.Build(pctx, android.BuildParams{ 180 Rule: android.Touch, 181 Output: getNdkFullTimestampFile(ctx), 182 Implicits: fullDepPaths, 183 }) 184} 185