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 	"android/soong/android"
     19 	"fmt"
     20 )
     21 
     22 type StlProperties struct {
     23 	// select the STL library to use.  Possible values are "libc++", "libc++_static",
     24 	// "stlport", "stlport_static", "ndk", "libstdc++", or "none".  Leave blank to select the
     25 	// default
     26 	Stl *string
     27 
     28 	SelectedStl string `blueprint:"mutated"`
     29 }
     30 
     31 type stl struct {
     32 	Properties StlProperties
     33 }
     34 
     35 func (stl *stl) props() []interface{} {
     36 	return []interface{}{&stl.Properties}
     37 }
     38 
     39 func (stl *stl) begin(ctx BaseModuleContext) {
     40 	stl.Properties.SelectedStl = func() string {
     41 		s := ""
     42 		if stl.Properties.Stl != nil {
     43 			s = *stl.Properties.Stl
     44 		}
     45 		if ctx.sdk() && ctx.Device() {
     46 			switch s {
     47 			case "":
     48 				return "ndk_system"
     49 			case "c++_shared", "c++_static",
     50 				"stlport_shared", "stlport_static",
     51 				"gnustl_static":
     52 				return "ndk_lib" + s
     53 			case "libc++":
     54 				return "ndk_libc++_shared"
     55 			case "libc++_static":
     56 				return "ndk_libc++_static"
     57 			case "none":
     58 				return ""
     59 			default:
     60 				ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s)
     61 				return ""
     62 			}
     63 		} else if ctx.Os() == android.Windows {
     64 			switch s {
     65 			case "libc++", "libc++_static", "libstdc++", "":
     66 				// libc++ is not supported on mingw
     67 				return "libstdc++"
     68 			case "none":
     69 				return ""
     70 			default:
     71 				ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s)
     72 				return ""
     73 			}
     74 		} else {
     75 			switch s {
     76 			case "libc++", "libc++_static":
     77 				return s
     78 			case "none":
     79 				return ""
     80 			case "":
     81 				if ctx.static() {
     82 					return "libc++_static"
     83 				} else {
     84 					return "libc++"
     85 				}
     86 			default:
     87 				ctx.ModuleErrorf("stl: %q is not a supported STL", s)
     88 				return ""
     89 			}
     90 		}
     91 	}()
     92 }
     93 
     94 func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
     95 	switch stl.Properties.SelectedStl {
     96 	case "libstdc++":
     97 		// Nothing
     98 	case "libc++", "libc++_static":
     99 		if stl.Properties.SelectedStl == "libc++" {
    100 			deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
    101 		} else {
    102 			deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
    103 		}
    104 		if ctx.toolchain().Bionic() {
    105 			if ctx.Arch().ArchType == android.Arm {
    106 				deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm")
    107 			}
    108 			if ctx.staticBinary() {
    109 				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
    110 			} else {
    111 				deps.SharedLibs = append(deps.SharedLibs, "libdl")
    112 			}
    113 		}
    114 	case "":
    115 		// None or error.
    116 	case "ndk_system":
    117 		// TODO: Make a system STL prebuilt for the NDK.
    118 		// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
    119 		// its own includes. The includes are handled in CCBase.Flags().
    120 		deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
    121 	case "ndk_libc++_shared":
    122 		deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl,
    123 			"libdl")
    124 	case "ndk_libc++_static":
    125 		deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
    126 		deps.SharedLibs = append(deps.SharedLibs, "libdl")
    127 	case "ndk_libstlport_shared":
    128 		deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
    129 	case "ndk_libstlport_static", "ndk_libgnustl_static":
    130 		deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
    131 	default:
    132 		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
    133 	}
    134 
    135 	return deps
    136 }
    137 
    138 func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
    139 	switch stl.Properties.SelectedStl {
    140 	case "libc++", "libc++_static":
    141 		flags.CFlags = append(flags.CFlags, "-D_USING_LIBCXX")
    142 		if !ctx.toolchain().Bionic() {
    143 			flags.CppFlags = append(flags.CppFlags, "-nostdinc++")
    144 			flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs")
    145 			flags.LdFlags = append(flags.LdFlags, "-lpthread", "-lm")
    146 			if ctx.staticBinary() {
    147 				flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...)
    148 			} else {
    149 				flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...)
    150 			}
    151 		} else {
    152 			if ctx.Arch().ArchType == android.Arm {
    153 				flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a")
    154 			}
    155 		}
    156 	case "libstdc++":
    157 		// Nothing
    158 	case "ndk_system":
    159 		ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
    160 		flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String())
    161 	case "ndk_libc++_shared", "ndk_libc++_static":
    162 		// TODO(danalbert): This really shouldn't be here...
    163 		flags.CppFlags = append(flags.CppFlags, "-std=c++11")
    164 	case "ndk_libstlport_shared", "ndk_libstlport_static", "ndk_libgnustl_static":
    165 		// Nothing
    166 	case "":
    167 		// None or error.
    168 		if !ctx.toolchain().Bionic() {
    169 			flags.CppFlags = append(flags.CppFlags, "-nostdinc++")
    170 			flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs")
    171 			if ctx.staticBinary() {
    172 				flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...)
    173 			} else {
    174 				flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...)
    175 			}
    176 		}
    177 	default:
    178 		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
    179 	}
    180 
    181 	return flags
    182 }
    183 
    184 var hostDynamicGccLibs, hostStaticGccLibs map[android.OsType][]string
    185 
    186 func init() {
    187 	hostDynamicGccLibs = map[android.OsType][]string{
    188 		android.Linux:  []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
    189 		android.Darwin: []string{"-lc", "-lSystem"},
    190 		android.Windows: []string{"-lmsvcr110", "-lmingw32", "-lgcc", "-lmoldname",
    191 			"-lmingwex", "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32",
    192 			"-lkernel32", "-lmingw32", "-lgcc", "-lmoldname", "-lmingwex",
    193 			"-lmsvcrt"},
    194 	}
    195 	hostStaticGccLibs = map[android.OsType][]string{
    196 		android.Linux:   []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"},
    197 		android.Darwin:  []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"},
    198 		android.Windows: []string{"NO_STATIC_HOST_BINARIES_ON_WINDOWS"},
    199 	}
    200 }
    201