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