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