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