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 ctx.VisitAllModules(func(module android.Module) { 104 if ccModule, ok := module.(*Module); ok { 105 baseName := ccModule.BaseModuleName() 106 if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() { 107 exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName) 108 } 109 } 110 }) 111 ctx.Strict("VENDOR_PUBLIC_LIBRARIES", makeVarsString(exportedVendorPublicLibraries)) 112 113 lsdumpPaths := *lsdumpPaths(ctx.Config()) 114 sort.Strings(lsdumpPaths) 115 ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " ")) 116 117 ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects()) 118 119 ctx.Strict("CLANG_COVERAGE_CONFIG_CFLAGS", strings.Join(clangCoverageCFlags, " ")) 120 ctx.Strict("CLANG_COVERAGE_CONFIG_COMMFLAGS", strings.Join(clangCoverageCommonFlags, " ")) 121 ctx.Strict("CLANG_COVERAGE_HOST_LDFLAGS", strings.Join(clangCoverageHostLdFlags, " ")) 122 ctx.Strict("CLANG_COVERAGE_INSTR_PROFILE", profileInstrFlag) 123 ctx.Strict("CLANG_COVERAGE_CONTINUOUS_FLAGS", strings.Join(clangContinuousCoverageFlags, " ")) 124 ctx.Strict("CLANG_COVERAGE_HWASAN_FLAGS", strings.Join(clangCoverageHWASanFlags, " ")) 125 126 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " ")) 127 128 ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " ")) 129 130 ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " ")) 131 ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " ")) 132 ctx.Strict("CFI_EXTRA_LDFLAGS", strings.Join(cfiLdflags, " ")) 133 134 ctx.Strict("INTEGER_OVERFLOW_EXTRA_CFLAGS", strings.Join(intOverflowCflags, " ")) 135 136 ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) 137 ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) 138 ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion) 139 ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion) 140 141 ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}") 142 ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks)) 143 ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}") 144 ctx.Strict("WITH_TIDY_FLAGS", "${config.TidyWithTidyFlags}") 145 146 ctx.Strict("AIDL_CPP", "${aidlCmd}") 147 ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " ")) 148 149 ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") 150 151 ctx.Strict("SOONG_STRIP_PATH", "${stripPath}") 152 ctx.Strict("XZ", "${xzCmd}") 153 ctx.Strict("CREATE_MINIDEBUGINFO", "${createMiniDebugInfo}") 154 155 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}") 156 if err != nil { 157 panic(err) 158 } 159 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 160 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 161 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 162 163 ndkKnownLibs := *getNDKKnownLibs(ctx.Config()) 164 sort.Strings(ndkKnownLibs) 165 ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " ")) 166 167 if hostTargets := ctx.Config().Targets[ctx.Config().BuildOS]; len(hostTargets) > 0 { 168 makeVarsToolchain(ctx, "", hostTargets[0]) 169 if len(hostTargets) > 1 { 170 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 171 } 172 } 173 174 if deviceTargets := ctx.Config().Targets[android.Android]; len(deviceTargets) > 0 { 175 makeVarsToolchain(ctx, "", deviceTargets[0]) 176 if len(deviceTargets) > 1 { 177 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 178 } 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 for variable, value := range sanitizerVariables { 259 ctx.Strict(secondPrefix+variable, value) 260 } 261 } 262 263 // This is used by external/gentoo/... 264 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 265 toolchain.ClangTriple()) 266 267 if target.Os == android.Darwin { 268 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 269 ctx.Strict(makePrefix+"NM", "${config.MacToolPath}/nm") 270 ctx.Strict(makePrefix+"OTOOL", "${config.MacToolPath}/otool") 271 ctx.Strict(makePrefix+"STRIP", "${config.MacStripPath}") 272 } else { 273 ctx.Strict(makePrefix+"AR", "${config.ClangBin}/llvm-ar") 274 ctx.Strict(makePrefix+"READELF", "${config.ClangBin}/llvm-readelf") 275 ctx.Strict(makePrefix+"NM", "${config.ClangBin}/llvm-nm") 276 ctx.Strict(makePrefix+"STRIP", "${config.ClangBin}/llvm-strip") 277 } 278 279 if target.Os.Class == android.Device { 280 ctx.Strict(makePrefix+"OBJCOPY", "${config.ClangBin}/llvm-objcopy") 281 ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld") 282 ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) 283 ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-") 284 } 285 286 if target.Os.Class == android.Host { 287 ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " ")) 288 } 289 290 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 291 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 292} 293 294func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 295 flags, err := ctx.Eval(val) 296 if err != nil { 297 panic(err) 298 } 299 300 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 301 if strings.HasPrefix(flags, prefix) { 302 flags = strings.TrimPrefix(flags, prefix) 303 flags = strings.TrimLeft(flags, " ") 304 s := strings.SplitN(flags, " ", 2) 305 dirs = append(dirs, s[0]) 306 if len(s) > 1 { 307 return strings.TrimLeft(s[1], " "), dirs, true 308 } 309 return "", dirs, true 310 } else { 311 return flags, dirs, false 312 } 313 } 314 315 flags = strings.TrimLeft(flags, " ") 316 for flags != "" { 317 found := false 318 flags, includes, found = extract(flags, includes, "-I") 319 if !found { 320 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 321 } 322 if !found { 323 panic(fmt.Errorf("Unexpected flag in %q", flags)) 324 } 325 } 326 327 return includes, systemIncludes 328} 329 330func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 331 rets := make([]string, len(checks)) 332 for i, check := range config.DefaultLocalTidyChecks { 333 rets[i] = check.PathPrefix + ":" + check.Checks 334 } 335 return strings.Join(rets, " ") 336} 337