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 15 package cc 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/google/blueprint" 22 23 "android/soong/android" 24 "android/soong/cc/config" 25 ) 26 27 func init() { 28 android.RegisterModuleType("ndk_prebuilt_library", ndkPrebuiltLibraryFactory) 29 android.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory) 30 android.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory) 31 android.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory) 32 } 33 34 // NDK prebuilt libraries. 35 // 36 // These differ from regular prebuilts in that they aren't stripped and usually aren't installed 37 // either (with the exception of the shared STLs, which are installed to the app's directory rather 38 // than to the system image). 39 40 func getNdkLibDir(ctx android.ModuleContext, toolchain config.Toolchain, version string) android.SourcePath { 41 suffix := "" 42 // Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a 43 // multilib toolchain and stores the libraries in "lib". 44 if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 { 45 suffix = "64" 46 } 47 return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s", 48 version, toolchain.Name(), suffix)) 49 } 50 51 func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain config.Toolchain, 52 ext string, version string) android.Path { 53 54 // NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION. 55 // We want to translate to just NAME.EXT 56 name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0] 57 dir := getNdkLibDir(ctx, toolchain, version) 58 return dir.Join(ctx, name+ext) 59 } 60 61 type ndkPrebuiltObjectLinker struct { 62 objectLinker 63 } 64 65 func (*ndkPrebuiltObjectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { 66 // NDK objects can't have any dependencies 67 return deps 68 } 69 70 func ndkPrebuiltObjectFactory() (blueprint.Module, []interface{}) { 71 module := newBaseModule(android.DeviceSupported, android.MultilibBoth) 72 module.linker = &ndkPrebuiltObjectLinker{ 73 objectLinker: objectLinker{ 74 baseLinker: NewBaseLinker(), 75 }, 76 } 77 module.Properties.HideFromMake = true 78 return module.Init() 79 } 80 81 func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags, 82 deps PathDeps, objs Objects) android.Path { 83 // A null build step, but it sets up the output path. 84 if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") { 85 ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name") 86 } 87 88 return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion()) 89 } 90 91 type ndkPrebuiltLibraryLinker struct { 92 *libraryDecorator 93 } 94 95 func (ndk *ndkPrebuiltLibraryLinker) linkerProps() []interface{} { 96 return append(ndk.libraryDecorator.linkerProps(), &ndk.Properties, &ndk.flagExporter.Properties) 97 } 98 99 func (*ndkPrebuiltLibraryLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { 100 // NDK libraries can't have any dependencies 101 return deps 102 } 103 104 func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) { 105 module, library := NewLibrary(android.DeviceSupported) 106 library.BuildOnlyShared() 107 linker := &ndkPrebuiltLibraryLinker{ 108 libraryDecorator: library, 109 } 110 module.compiler = nil 111 module.linker = linker 112 module.installer = nil 113 module.stl = nil 114 module.Properties.HideFromMake = true 115 return module.Init() 116 } 117 118 func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags, 119 deps PathDeps, objs Objects) android.Path { 120 // A null build step, but it sets up the output path. 121 ndk.exportIncludes(ctx, "-isystem") 122 123 return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(), 124 ctx.sdkVersion()) 125 } 126 127 // The NDK STLs are slightly different from the prebuilt system libraries: 128 // * Are not specific to each platform version. 129 // * The libraries are not in a predictable location for each STL. 130 131 type ndkPrebuiltStlLinker struct { 132 ndkPrebuiltLibraryLinker 133 } 134 135 func ndkPrebuiltSharedStlFactory() (blueprint.Module, []interface{}) { 136 module, library := NewLibrary(android.DeviceSupported) 137 library.BuildOnlyShared() 138 linker := &ndkPrebuiltStlLinker{ 139 ndkPrebuiltLibraryLinker: ndkPrebuiltLibraryLinker{ 140 libraryDecorator: library, 141 }, 142 } 143 module.compiler = nil 144 module.linker = linker 145 module.installer = nil 146 module.Properties.HideFromMake = true 147 return module.Init() 148 } 149 150 func ndkPrebuiltStaticStlFactory() (blueprint.Module, []interface{}) { 151 module, library := NewLibrary(android.DeviceSupported) 152 library.BuildOnlyStatic() 153 linker := &ndkPrebuiltStlLinker{ 154 ndkPrebuiltLibraryLinker: ndkPrebuiltLibraryLinker{ 155 libraryDecorator: library, 156 }, 157 } 158 module.compiler = nil 159 module.linker = linker 160 module.installer = nil 161 module.Properties.HideFromMake = true 162 return module.Init() 163 } 164 165 func getNdkStlLibDir(ctx android.ModuleContext, toolchain config.Toolchain, stl string) android.SourcePath { 166 gccVersion := toolchain.GccVersion() 167 var libDir string 168 switch stl { 169 case "libstlport": 170 libDir = "cxx-stl/stlport/libs" 171 case "libc++": 172 libDir = "cxx-stl/llvm-libc++/libs" 173 case "libgnustl": 174 libDir = fmt.Sprintf("cxx-stl/gnu-libstdc++/%s/libs", gccVersion) 175 } 176 177 if libDir != "" { 178 ndkSrcRoot := "prebuilts/ndk/current/sources" 179 return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0]) 180 } 181 182 ctx.ModuleErrorf("Unknown NDK STL: %s", stl) 183 return android.PathForSource(ctx, "") 184 } 185 186 func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, 187 deps PathDeps, objs Objects) android.Path { 188 // A null build step, but it sets up the output path. 189 if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") { 190 ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name") 191 } 192 193 ndk.exportIncludes(ctx, "-I") 194 195 libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_") 196 libExt := flags.Toolchain.ShlibSuffix() 197 if ndk.static() { 198 libExt = staticLibraryExtension 199 } 200 201 stlName := strings.TrimSuffix(libName, "_shared") 202 stlName = strings.TrimSuffix(stlName, "_static") 203 libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName) 204 return libDir.Join(ctx, libName+libExt) 205 } 206