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 15package cc 16 17import ( 18 "fmt" 19 "sort" 20 "strings" 21 "sync" 22 23 "android/soong/android" 24 "android/soong/cc/config" 25) 26 27var ( 28 modulesWarningsAllowedKey = android.NewOnceKey("ModulesWarningsAllowed") 29 modulesUsingWnoErrorKey = android.NewOnceKey("ModulesUsingWnoError") 30 modulesMissingProfileFileKey = android.NewOnceKey("ModulesMissingProfileFile") 31 sanitizerVariables = map[string]string{ 32 "ADDRESS_SANITIZER_RUNTIME_LIBRARY": config.AddressSanitizerRuntimeLibrary(), 33 "HWADDRESS_SANITIZER_RUNTIME_LIBRARY": config.HWAddressSanitizerRuntimeLibrary(), 34 "HWADDRESS_SANITIZER_STATIC_LIBRARY": config.HWAddressSanitizerStaticLibrary(), 35 "UBSAN_RUNTIME_LIBRARY": config.UndefinedBehaviorSanitizerRuntimeLibrary(), 36 "UBSAN_MINIMAL_RUNTIME_LIBRARY": config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(), 37 "TSAN_RUNTIME_LIBRARY": config.ThreadSanitizerRuntimeLibrary(), 38 "SCUDO_RUNTIME_LIBRARY": config.ScudoRuntimeLibrary(), 39 "SCUDO_MINIMAL_RUNTIME_LIBRARY": config.ScudoMinimalRuntimeLibrary(), 40 } 41) 42 43func init() { 44 android.RegisterMakeVarsProvider(pctx, makeVarsProvider) 45} 46 47func getNamedMapForConfig(config android.Config, key android.OnceKey) *sync.Map { 48 return config.Once(key, func() interface{} { 49 return &sync.Map{} 50 }).(*sync.Map) 51} 52 53func makeStringOfKeys(ctx android.MakeVarsContext, key android.OnceKey) string { 54 set := getNamedMapForConfig(ctx.Config(), key) 55 keys := []string{} 56 set.Range(func(key interface{}, value interface{}) bool { 57 keys = append(keys, key.(string)) 58 return true 59 }) 60 sort.Strings(keys) 61 return strings.Join(keys, " ") 62} 63 64func makeStringOfWarningAllowedProjects() string { 65 allProjects := append([]string{}, config.WarningAllowedProjects...) 66 sort.Strings(allProjects) 67 // Makefile rules use pattern "path/%" to match module paths. 68 if len(allProjects) > 0 { 69 return strings.Join(allProjects, "% ") + "%" 70 } else { 71 return "" 72 } 73} 74 75type notOnHostContext struct { 76} 77 78func (c *notOnHostContext) Host() bool { 79 return false 80} 81 82func makeVarsProvider(ctx android.MakeVarsContext) { 83 ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}") 84 ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}") 85 ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}") 86 ctx.Strict("LLVM_PREBUILTS_PATH", "${config.ClangBin}") 87 ctx.Strict("CLANG", "${config.ClangBin}/clang") 88 ctx.Strict("CLANG_CXX", "${config.ClangBin}/clang++") 89 ctx.Strict("LLVM_AS", "${config.ClangBin}/llvm-as") 90 ctx.Strict("LLVM_LINK", "${config.ClangBin}/llvm-link") 91 ctx.Strict("LLVM_OBJCOPY", "${config.ClangBin}/llvm-objcopy") 92 ctx.Strict("LLVM_STRIP", "${config.ClangBin}/llvm-strip") 93 ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy") 94 ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " ")) 95 96 ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}") 97 ctx.Strict("RS_LLVM_PREBUILTS_BASE", "${config.RSClangBase}") 98 ctx.Strict("RS_LLVM_PREBUILTS_PATH", "${config.RSLLVMPrebuiltsPath}") 99 ctx.Strict("RS_LLVM_INCLUDES", "${config.RSIncludePath}") 100 ctx.Strict("RS_CLANG", "${config.RSLLVMPrebuiltsPath}/clang") 101 ctx.Strict("RS_LLVM_AS", "${config.RSLLVMPrebuiltsPath}/llvm-as") 102 ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link") 103 104 ctx.Strict("CLANG_EXTERNAL_CFLAGS", "${config.ExternalCflags}") 105 ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}") 106 ctx.Strict("GLOBAL_CLANG_CFLAGS_64_NO_OVERRIDE", "${config.NoOverride64GlobalCflags}") 107 ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "") 108 ctx.Strict("GLOBAL_CLANG_EXTERNAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideExternalGlobalCflags}") 109 110 // Filter vendor_public_library that are exported to make 111 exportedVendorPublicLibraries := []string{} 112 ctx.VisitAllModules(func(module android.Module) { 113 if ccModule, ok := module.(*Module); ok { 114 baseName := ccModule.BaseModuleName() 115 if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() { 116 if !inList(baseName, exportedVendorPublicLibraries) { 117 exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName) 118 } 119 } 120 } 121 }) 122 sort.Strings(exportedVendorPublicLibraries) 123 ctx.Strict("VENDOR_PUBLIC_LIBRARIES", strings.Join(exportedVendorPublicLibraries, " ")) 124 125 sort.Strings(lsdumpPaths) 126 ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " ")) 127 128 ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects()) 129 ctx.Strict("SOONG_MODULES_WARNINGS_ALLOWED", makeStringOfKeys(ctx, modulesWarningsAllowedKey)) 130 ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeStringOfKeys(ctx, modulesUsingWnoErrorKey)) 131 ctx.Strict("SOONG_MODULES_MISSING_PGO_PROFILE_FILE", makeStringOfKeys(ctx, modulesMissingProfileFileKey)) 132 133 ctx.Strict("CLANG_COVERAGE_CONFIG_CFLAGS", strings.Join(clangCoverageCFlags, " ")) 134 ctx.Strict("CLANG_COVERAGE_CONFIG_COMMFLAGS", strings.Join(clangCoverageCommonFlags, " ")) 135 ctx.Strict("CLANG_COVERAGE_HOST_LDFLAGS", strings.Join(clangCoverageHostLdFlags, " ")) 136 ctx.Strict("CLANG_COVERAGE_INSTR_PROFILE", profileInstrFlag) 137 ctx.Strict("CLANG_COVERAGE_CONTINUOUS_FLAGS", strings.Join(clangContinuousCoverageFlags, " ")) 138 ctx.Strict("CLANG_COVERAGE_HWASAN_FLAGS", strings.Join(clangCoverageHWASanFlags, " ")) 139 140 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " ")) 141 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " ")) 142 143 ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " ")) 144 ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ",")) 145 146 ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " ")) 147 ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " ")) 148 ctx.Strict("CFI_EXTRA_LDFLAGS", strings.Join(cfiLdflags, " ")) 149 150 ctx.Strict("INTEGER_OVERFLOW_EXTRA_CFLAGS", strings.Join(intOverflowCflags, " ")) 151 152 ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) 153 ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) 154 ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion) 155 ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion) 156 157 ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}") 158 ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks)) 159 ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}") 160 ctx.Strict("WITH_TIDY_FLAGS", "${config.TidyWithTidyFlags}") 161 162 ctx.Strict("AIDL_CPP", "${aidlCmd}") 163 ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " ")) 164 165 ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") 166 167 ctx.Strict("SOONG_STRIP_PATH", "${stripPath}") 168 ctx.Strict("XZ", "${xzCmd}") 169 ctx.Strict("CREATE_MINIDEBUGINFO", "${createMiniDebugInfo}") 170 171 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}") 172 if err != nil { 173 panic(err) 174 } 175 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 176 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 177 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 178 179 ndkKnownLibs := *getNDKKnownLibs(ctx.Config()) 180 sort.Strings(ndkKnownLibs) 181 ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " ")) 182 183 hostTargets := ctx.Config().Targets[ctx.Config().BuildOS] 184 makeVarsToolchain(ctx, "", hostTargets[0]) 185 if len(hostTargets) > 1 { 186 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 187 } 188 189 deviceTargets := ctx.Config().Targets[android.Android] 190 makeVarsToolchain(ctx, "", deviceTargets[0]) 191 if len(deviceTargets) > 1 { 192 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 193 } 194 195 makeLlndkVars(ctx) 196} 197 198func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, 199 target android.Target) { 200 var typePrefix string 201 switch target.Os.Class { 202 case android.Host: 203 typePrefix = "HOST_" 204 case android.Device: 205 typePrefix = "TARGET_" 206 } 207 makePrefix := secondPrefix + typePrefix 208 209 toolchain := config.FindToolchain(target.Os, target.Arch) 210 211 var productExtraCflags string 212 var productExtraLdflags string 213 214 hod := "Host" 215 if target.Os.Class == android.Device { 216 hod = "Device" 217 } 218 219 if target.Os.Class == android.Host && ctx.Config().HostStaticBinaries() { 220 productExtraLdflags += "-static" 221 } 222 223 includeFlags, err := ctx.Eval(toolchain.IncludeFlags()) 224 if err != nil { 225 panic(err) 226 } 227 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 228 ctx.StrictRaw(makePrefix+"C_INCLUDES", strings.Join(includes, " ")) 229 ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " ")) 230 231 if target.Arch.ArchType == android.Arm { 232 flags, err := toolchain.InstructionSetFlags("arm") 233 if err != nil { 234 panic(err) 235 } 236 ctx.Strict(makePrefix+"arm_CFLAGS", flags) 237 238 flags, err = toolchain.InstructionSetFlags("thumb") 239 if err != nil { 240 panic(err) 241 } 242 ctx.Strict(makePrefix+"thumb_CFLAGS", flags) 243 } 244 245 clangPrefix := secondPrefix + "CLANG_" + typePrefix 246 247 ctx.Strict(clangPrefix+"TRIPLE", toolchain.ClangTriple()) 248 ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 249 toolchain.Cflags(), 250 "${config.CommonGlobalCflags}", 251 fmt.Sprintf("${config.%sGlobalCflags}", hod), 252 toolchain.ToolchainCflags(), 253 productExtraCflags, 254 }, " ")) 255 ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 256 "${config.CommonGlobalCppflags}", 257 fmt.Sprintf("${config.%sGlobalCppflags}", hod), 258 toolchain.Cppflags(), 259 }, " ")) 260 ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 261 fmt.Sprintf("${config.%sGlobalLdflags}", hod), 262 toolchain.Ldflags(), 263 toolchain.ToolchainLdflags(), 264 productExtraLdflags, 265 }, " ")) 266 ctx.Strict(clangPrefix+"GLOBAL_LLDFLAGS", strings.Join([]string{ 267 fmt.Sprintf("${config.%sGlobalLldflags}", hod), 268 toolchain.Lldflags(), 269 toolchain.ToolchainLdflags(), 270 productExtraLdflags, 271 }, " ")) 272 273 if target.Os.Class == android.Device { 274 for variable, value := range sanitizerVariables { 275 ctx.Strict(secondPrefix+variable, value) 276 } 277 } 278 279 // This is used by external/gentoo/... 280 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 281 toolchain.ClangTriple()) 282 283 if target.Os == android.Darwin { 284 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 285 ctx.Strict(makePrefix+"NM", "${config.MacToolPath}/nm") 286 ctx.Strict(makePrefix+"OTOOL", "${config.MacToolPath}/otool") 287 ctx.Strict(makePrefix+"STRIP", "${config.MacStripPath}") 288 } else { 289 ctx.Strict(makePrefix+"AR", "${config.ClangBin}/llvm-ar") 290 ctx.Strict(makePrefix+"READELF", "${config.ClangBin}/llvm-readelf") 291 ctx.Strict(makePrefix+"NM", "${config.ClangBin}/llvm-nm") 292 ctx.Strict(makePrefix+"STRIP", "${config.ClangBin}/llvm-strip") 293 } 294 295 if target.Os.Class == android.Device { 296 ctx.Strict(makePrefix+"OBJCOPY", "${config.ClangBin}/llvm-objcopy") 297 ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld") 298 ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) 299 ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-") 300 } 301 302 if target.Os.Class == android.Host { 303 ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " ")) 304 } 305 306 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 307 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 308} 309 310func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 311 flags, err := ctx.Eval(val) 312 if err != nil { 313 panic(err) 314 } 315 316 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 317 if strings.HasPrefix(flags, prefix) { 318 flags = strings.TrimPrefix(flags, prefix) 319 flags = strings.TrimLeft(flags, " ") 320 s := strings.SplitN(flags, " ", 2) 321 dirs = append(dirs, s[0]) 322 if len(s) > 1 { 323 return strings.TrimLeft(s[1], " "), dirs, true 324 } 325 return "", dirs, true 326 } else { 327 return flags, dirs, false 328 } 329 } 330 331 flags = strings.TrimLeft(flags, " ") 332 for flags != "" { 333 found := false 334 flags, includes, found = extract(flags, includes, "-I") 335 if !found { 336 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 337 } 338 if !found { 339 panic(fmt.Errorf("Unexpected flag in %q", flags)) 340 } 341 } 342 343 return includes, systemIncludes 344} 345 346func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 347 rets := make([]string, len(checks)) 348 for i, check := range config.DefaultLocalTidyChecks { 349 rets[i] = check.PathPrefix + ":" + check.Checks 350 } 351 return strings.Join(rets, " ") 352} 353