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