1// Copyright 2015 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 15package config 16 17import ( 18 "fmt" 19 "path/filepath" 20 21 "android/soong/android" 22) 23 24type toolchainFactory func(arch android.Arch) Toolchain 25 26var toolchainFactories = make(map[android.OsType]map[android.ArchType]toolchainFactory) 27 28func registerToolchainFactory(os android.OsType, arch android.ArchType, factory toolchainFactory) { 29 if toolchainFactories[os] == nil { 30 toolchainFactories[os] = make(map[android.ArchType]toolchainFactory) 31 } 32 toolchainFactories[os][arch] = factory 33} 34 35type toolchainContext interface { 36 Os() android.OsType 37 Arch() android.Arch 38} 39 40type conversionContext interface { 41 BazelConversionMode() bool 42} 43 44func FindToolchainWithContext(ctx toolchainContext) Toolchain { 45 t, err := findToolchain(ctx.Os(), ctx.Arch()) 46 if err != nil { 47 if c, ok := ctx.(conversionContext); ok && c.BazelConversionMode() { 48 // TODO(b/179123288): determine conversion for toolchain 49 return &toolchainX86_64{} 50 } else { 51 panic(err) 52 } 53 } 54 return t 55} 56 57func FindToolchain(os android.OsType, arch android.Arch) Toolchain { 58 t, err := findToolchain(os, arch) 59 if err != nil { 60 panic(err) 61 } 62 return t 63} 64 65func findToolchain(os android.OsType, arch android.Arch) (Toolchain, error) { 66 factory := toolchainFactories[os][arch.ArchType] 67 if factory == nil { 68 return nil, fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String()) 69 } 70 return factory(arch), nil 71} 72 73type Toolchain interface { 74 Name() string 75 76 GccRoot() string 77 GccTriple() string 78 // GccVersion should return a real value, not a ninja reference 79 GccVersion() string 80 ToolPath() string 81 82 IncludeFlags() string 83 84 ClangTriple() string 85 ToolchainClangCflags() string 86 ToolchainClangLdflags() string 87 ClangAsflags() string 88 ClangCflags() string 89 ClangCppflags() string 90 ClangLdflags() string 91 ClangLldflags() string 92 ClangInstructionSetFlags(string) (string, error) 93 94 ndkTriple() string 95 96 YasmFlags() string 97 98 WindresFlags() string 99 100 Is64Bit() bool 101 102 ShlibSuffix() string 103 ExecutableSuffix() string 104 105 LibclangRuntimeLibraryArch() string 106 107 AvailableLibraries() []string 108 109 Bionic() bool 110} 111 112type toolchainBase struct { 113} 114 115func (t *toolchainBase) ndkTriple() string { 116 return "" 117} 118 119func NDKTriple(toolchain Toolchain) string { 120 triple := toolchain.ndkTriple() 121 if triple == "" { 122 // Use the clang triple if there is no explicit NDK triple 123 triple = toolchain.ClangTriple() 124 } 125 return triple 126} 127 128func (toolchainBase) ClangInstructionSetFlags(s string) (string, error) { 129 if s != "" { 130 return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s) 131 } 132 return "", nil 133} 134 135func (toolchainBase) ToolchainClangCflags() string { 136 return "" 137} 138 139func (toolchainBase) ToolchainClangLdflags() string { 140 return "" 141} 142 143func (toolchainBase) ShlibSuffix() string { 144 return ".so" 145} 146 147func (toolchainBase) ExecutableSuffix() string { 148 return "" 149} 150 151func (toolchainBase) ClangAsflags() string { 152 return "" 153} 154 155func (toolchainBase) YasmFlags() string { 156 return "" 157} 158 159func (toolchainBase) WindresFlags() string { 160 return "" 161} 162 163func (toolchainBase) LibclangRuntimeLibraryArch() string { 164 return "" 165} 166 167func (toolchainBase) AvailableLibraries() []string { 168 return []string{} 169} 170 171func (toolchainBase) Bionic() bool { 172 return true 173} 174 175func (t toolchainBase) ToolPath() string { 176 return "" 177} 178 179type toolchain64Bit struct { 180 toolchainBase 181} 182 183func (toolchain64Bit) Is64Bit() bool { 184 return true 185} 186 187type toolchain32Bit struct { 188 toolchainBase 189} 190 191func (toolchain32Bit) Is64Bit() bool { 192 return false 193} 194 195func variantOrDefault(variants map[string]string, choice string) string { 196 if ret, ok := variants[choice]; ok { 197 return ret 198 } 199 return variants[""] 200} 201 202func addPrefix(list []string, prefix string) []string { 203 for i := range list { 204 list[i] = prefix + list[i] 205 } 206 return list 207} 208 209func LibclangRuntimeLibrary(t Toolchain, library string) string { 210 arch := t.LibclangRuntimeLibraryArch() 211 if arch == "" { 212 return "" 213 } 214 if !t.Bionic() { 215 return "libclang_rt." + library + "-" + arch 216 } 217 return "libclang_rt." + library + "-" + arch + "-android" 218} 219 220func BuiltinsRuntimeLibrary(t Toolchain) string { 221 return LibclangRuntimeLibrary(t, "builtins") 222} 223 224func AddressSanitizerRuntimeLibrary(t Toolchain) string { 225 return LibclangRuntimeLibrary(t, "asan") 226} 227 228func HWAddressSanitizerRuntimeLibrary(t Toolchain) string { 229 return LibclangRuntimeLibrary(t, "hwasan") 230} 231 232func HWAddressSanitizerStaticLibrary(t Toolchain) string { 233 return LibclangRuntimeLibrary(t, "hwasan_static") 234} 235 236func UndefinedBehaviorSanitizerRuntimeLibrary(t Toolchain) string { 237 return LibclangRuntimeLibrary(t, "ubsan_standalone") 238} 239 240func UndefinedBehaviorSanitizerMinimalRuntimeLibrary(t Toolchain) string { 241 return LibclangRuntimeLibrary(t, "ubsan_minimal") 242} 243 244func ThreadSanitizerRuntimeLibrary(t Toolchain) string { 245 return LibclangRuntimeLibrary(t, "tsan") 246} 247 248func ScudoRuntimeLibrary(t Toolchain) string { 249 return LibclangRuntimeLibrary(t, "scudo") 250} 251 252func ScudoMinimalRuntimeLibrary(t Toolchain) string { 253 return LibclangRuntimeLibrary(t, "scudo_minimal") 254} 255 256func LibFuzzerRuntimeLibrary(t Toolchain) string { 257 return LibclangRuntimeLibrary(t, "fuzzer") 258} 259 260func ToolPath(t Toolchain) string { 261 if p := t.ToolPath(); p != "" { 262 return p 263 } 264 return filepath.Join(t.GccRoot(), t.GccTriple(), "bin") 265} 266 267var inList = android.InList 268