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 "sort" 20 "strings" 21 22 "android/soong/android" 23 "android/soong/cc/config" 24 ) 25 26 func init() { 27 android.RegisterMakeVarsProvider(pctx, makeVarsProvider) 28 } 29 30 func makeVarsProvider(ctx android.MakeVarsContext) { 31 ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}") 32 ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}") 33 ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}") 34 ctx.Strict("LLVM_PREBUILTS_PATH", "${config.ClangBin}") 35 ctx.Strict("CLANG", "${config.ClangBin}/clang") 36 ctx.Strict("CLANG_CXX", "${config.ClangBin}/clang++") 37 ctx.Strict("LLVM_AS", "${config.ClangBin}/llvm-as") 38 ctx.Strict("LLVM_LINK", "${config.ClangBin}/llvm-link") 39 ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy") 40 ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " ")) 41 42 ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}") 43 ctx.Strict("RS_LLVM_PREBUILTS_BASE", "${config.RSClangBase}") 44 ctx.Strict("RS_LLVM_PREBUILTS_PATH", "${config.RSLLVMPrebuiltsPath}") 45 ctx.Strict("RS_LLVM_INCLUDES", "${config.RSIncludePath}") 46 ctx.Strict("RS_CLANG", "${config.RSLLVMPrebuiltsPath}/clang") 47 ctx.Strict("RS_LLVM_AS", "${config.RSLLVMPrebuiltsPath}/llvm-as") 48 ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link") 49 50 ctx.Strict("GLOBAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}") 51 ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.ClangExtraNoOverrideCflags}") 52 ctx.Strict("GLOBAL_CPPFLAGS_NO_OVERRIDE", "") 53 ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "") 54 ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " ")) 55 56 if ctx.Config().ProductVariables.DeviceVndkVersion != nil { 57 ctx.Strict("BOARD_VNDK_VERSION", *ctx.Config().ProductVariables.DeviceVndkVersion) 58 } else { 59 ctx.Strict("BOARD_VNDK_VERSION", "") 60 } 61 62 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", asanCflags) 63 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", asanLdflags) 64 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", asanLibs) 65 66 ctx.Strict("CFI_EXTRA_CFLAGS", cfiCflags) 67 ctx.Strict("CFI_EXTRA_LDFLAGS", cfiLdflags) 68 69 ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) 70 ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) 71 ctx.Strict("DEFAULT_GCC_CPP_STD_VERSION", config.GccCppStdVersion) 72 ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion) 73 ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion) 74 75 ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}") 76 ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks)) 77 ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}") 78 79 ctx.Strict("AIDL_CPP", "${aidlCmd}") 80 81 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes} ${config.CommonGlobalSystemIncludes}") 82 if err != nil { 83 panic(err) 84 } 85 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 86 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 87 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 88 89 sort.Strings(ndkMigratedLibs) 90 ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " ")) 91 92 hostTargets := ctx.Config().Targets[android.Host] 93 makeVarsToolchain(ctx, "", hostTargets[0]) 94 if len(hostTargets) > 1 { 95 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 96 } 97 98 crossTargets := ctx.Config().Targets[android.HostCross] 99 if len(crossTargets) > 0 { 100 makeVarsToolchain(ctx, "", crossTargets[0]) 101 if len(crossTargets) > 1 { 102 makeVarsToolchain(ctx, "2ND_", crossTargets[1]) 103 } 104 } 105 106 deviceTargets := ctx.Config().Targets[android.Device] 107 makeVarsToolchain(ctx, "", deviceTargets[0]) 108 if len(deviceTargets) > 1 { 109 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 110 } 111 } 112 113 func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, 114 target android.Target) { 115 var typePrefix string 116 switch target.Os.Class { 117 case android.Host: 118 typePrefix = "HOST_" 119 case android.HostCross: 120 typePrefix = "HOST_CROSS_" 121 case android.Device: 122 typePrefix = "TARGET_" 123 } 124 makePrefix := secondPrefix + typePrefix 125 126 toolchain := config.FindToolchain(target.Os, target.Arch) 127 128 var productExtraCflags string 129 var productExtraLdflags string 130 131 hod := "Host" 132 if target.Os.Class == android.Device { 133 hod = "Device" 134 } 135 136 if target.Os.Class == android.Device && Bool(ctx.Config().ProductVariables.Brillo) { 137 productExtraCflags += "-D__BRILLO__" 138 } 139 if target.Os.Class == android.Host && Bool(ctx.Config().ProductVariables.HostStaticBinaries) { 140 productExtraLdflags += "-static" 141 } 142 143 ctx.Strict(makePrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 144 toolchain.Cflags(), 145 "${config.CommonGlobalCflags}", 146 fmt.Sprintf("${config.%sGlobalCflags}", hod), 147 toolchain.ToolchainCflags(), 148 productExtraCflags, 149 }, " ")) 150 ctx.Strict(makePrefix+"GLOBAL_CONLYFLAGS", strings.Join([]string{ 151 "${config.CommonGlobalConlyflags}", 152 }, " ")) 153 ctx.Strict(makePrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 154 "${config.CommonGlobalCppflags}", 155 toolchain.Cppflags(), 156 }, " ")) 157 ctx.Strict(makePrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 158 toolchain.Ldflags(), 159 toolchain.ToolchainLdflags(), 160 productExtraLdflags, 161 }, " ")) 162 163 includeFlags, err := ctx.Eval(toolchain.IncludeFlags()) 164 if err != nil { 165 panic(err) 166 } 167 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 168 ctx.StrictRaw(makePrefix+"C_INCLUDES", strings.Join(includes, " ")) 169 ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " ")) 170 171 if target.Arch.ArchType == android.Arm { 172 flags, err := toolchain.InstructionSetFlags("arm") 173 if err != nil { 174 panic(err) 175 } 176 ctx.Strict(makePrefix+"arm_CFLAGS", flags) 177 178 flags, err = toolchain.InstructionSetFlags("thumb") 179 if err != nil { 180 panic(err) 181 } 182 ctx.Strict(makePrefix+"thumb_CFLAGS", flags) 183 } 184 185 if toolchain.ClangSupported() { 186 clangPrefix := secondPrefix + "CLANG_" + typePrefix 187 clangExtras := "-target " + toolchain.ClangTriple() 188 clangExtras += " -B" + config.ToolPath(toolchain) 189 190 ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 191 toolchain.ClangCflags(), 192 "${config.CommonClangGlobalCflags}", 193 fmt.Sprintf("${config.%sClangGlobalCflags}", hod), 194 toolchain.ToolchainClangCflags(), 195 clangExtras, 196 productExtraCflags, 197 }, " ")) 198 ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 199 "${config.CommonClangGlobalCppflags}", 200 toolchain.ClangCppflags(), 201 }, " ")) 202 ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 203 toolchain.ClangLdflags(), 204 toolchain.ToolchainClangLdflags(), 205 productExtraLdflags, 206 clangExtras, 207 }, " ")) 208 209 if target.Os.Class == android.Device { 210 ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so")) 211 ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so")) 212 } 213 214 // This is used by external/gentoo/... 215 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 216 toolchain.ClangTriple()) 217 } 218 219 ctx.Strict(makePrefix+"CC", gccCmd(toolchain, "gcc")) 220 ctx.Strict(makePrefix+"CXX", gccCmd(toolchain, "g++")) 221 222 if target.Os == android.Darwin { 223 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 224 } else { 225 ctx.Strict(makePrefix+"AR", gccCmd(toolchain, "ar")) 226 ctx.Strict(makePrefix+"READELF", gccCmd(toolchain, "readelf")) 227 ctx.Strict(makePrefix+"NM", gccCmd(toolchain, "nm")) 228 } 229 230 if target.Os == android.Windows { 231 ctx.Strict(makePrefix+"OBJDUMP", gccCmd(toolchain, "objdump")) 232 } 233 234 if target.Os.Class == android.Device { 235 ctx.Strict(makePrefix+"OBJCOPY", gccCmd(toolchain, "objcopy")) 236 ctx.Strict(makePrefix+"LD", gccCmd(toolchain, "ld")) 237 ctx.Strict(makePrefix+"STRIP", gccCmd(toolchain, "strip")) 238 ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion()) 239 ctx.Strict(makePrefix+"NDK_GCC_VERSION", toolchain.GccVersion()) 240 ctx.Strict(makePrefix+"NDK_TRIPLE", toolchain.ClangTriple()) 241 } 242 243 ctx.Strict(makePrefix+"TOOLCHAIN_ROOT", toolchain.GccRoot()) 244 ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, "")) 245 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 246 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 247 } 248 249 func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 250 flags, err := ctx.Eval(val) 251 if err != nil { 252 panic(err) 253 } 254 255 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 256 if strings.HasPrefix(flags, prefix) { 257 flags = strings.TrimPrefix(flags, prefix) 258 flags = strings.TrimLeft(flags, " ") 259 s := strings.SplitN(flags, " ", 2) 260 dirs = append(dirs, s[0]) 261 if len(s) > 1 { 262 return strings.TrimLeft(s[1], " "), dirs, true 263 } 264 return "", dirs, true 265 } else { 266 return flags, dirs, false 267 } 268 } 269 270 flags = strings.TrimLeft(flags, " ") 271 for flags != "" { 272 found := false 273 flags, includes, found = extract(flags, includes, "-I") 274 if !found { 275 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 276 } 277 if !found { 278 panic(fmt.Errorf("Unexpected flag in %q", flags)) 279 } 280 } 281 282 return includes, systemIncludes 283 } 284 285 func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 286 rets := make([]string, len(checks)) 287 for i, check := range config.DefaultLocalTidyChecks { 288 rets[i] = check.PathPrefix + ":" + check.Checks 289 } 290 return strings.Join(rets, " ") 291 } 292