Home | History | Annotate | Download | only in cc
      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 	minVersionString := "minimum"
    145 	noStlString := "none"
    146 	module.Properties.Sdk_version = &minVersionString
    147 	module.stl.Properties.Stl = &noStlString
    148 	return module.Init()
    149 }
    150 
    151 func ndkPrebuiltStaticStlFactory() android.Module {
    152 	module, library := NewLibrary(android.DeviceSupported)
    153 	library.BuildOnlyStatic()
    154 	linker := &ndkPrebuiltStlLinker{
    155 		ndkPrebuiltLibraryLinker: ndkPrebuiltLibraryLinker{
    156 			libraryDecorator: library,
    157 		},
    158 	}
    159 	module.compiler = nil
    160 	module.linker = linker
    161 	module.installer = nil
    162 	module.Properties.HideFromMake = true
    163 	return module.Init()
    164 }
    165 
    166 func getNdkStlLibDir(ctx android.ModuleContext, stl string) android.SourcePath {
    167 	libDir := "cxx-stl/llvm-libc++/libs"
    168 	ndkSrcRoot := "prebuilts/ndk/current/sources"
    169 	return android.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
    170 }
    171 
    172 func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
    173 	deps PathDeps, objs Objects) android.Path {
    174 	// A null build step, but it sets up the output path.
    175 	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
    176 		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
    177 	}
    178 
    179 	ndk.exportIncludes(ctx, "-isystem")
    180 
    181 	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
    182 	libExt := flags.Toolchain.ShlibSuffix()
    183 	if ndk.static() {
    184 		libExt = staticLibraryExtension
    185 	}
    186 
    187 	stlName := strings.TrimSuffix(libName, "_shared")
    188 	stlName = strings.TrimSuffix(stlName, "_static")
    189 	libDir := getNdkStlLibDir(ctx, stlName)
    190 	return libDir.Join(ctx, libName+libExt)
    191 }
    192