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 	"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