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 vendorPublicLibraries := vendorPublicLibraries(ctx.Config()) 75 76 ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}") 77 ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}") 78 ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}") 79 ctx.Strict("LLVM_PREBUILTS_PATH", "${config.ClangBin}") 80 ctx.Strict("CLANG", "${config.ClangBin}/clang") 81 ctx.Strict("CLANG_CXX", "${config.ClangBin}/clang++") 82 ctx.Strict("LLVM_AS", "${config.ClangBin}/llvm-as") 83 ctx.Strict("LLVM_LINK", "${config.ClangBin}/llvm-link") 84 ctx.Strict("LLVM_OBJCOPY", "${config.ClangBin}/llvm-objcopy") 85 ctx.Strict("LLVM_STRIP", "${config.ClangBin}/llvm-strip") 86 ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy") 87 ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " ")) 88 89 ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}") 90 ctx.Strict("RS_LLVM_PREBUILTS_BASE", "${config.RSClangBase}") 91 ctx.Strict("RS_LLVM_PREBUILTS_PATH", "${config.RSLLVMPrebuiltsPath}") 92 ctx.Strict("RS_LLVM_INCLUDES", "${config.RSIncludePath}") 93 ctx.Strict("RS_CLANG", "${config.RSLLVMPrebuiltsPath}/clang") 94 ctx.Strict("RS_LLVM_AS", "${config.RSLLVMPrebuiltsPath}/llvm-as") 95 ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link") 96 97 ctx.Strict("CLANG_EXTERNAL_CFLAGS", "${config.ClangExternalCflags}") 98 ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideClangGlobalCflags}") 99 ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "") 100 101 ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion()) 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 inList(baseName, *vendorPublicLibraries) && 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("M4", "${m4Cmd}") 152 153 ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") 154 155 ctx.Strict("SOONG_STRIP_PATH", "${stripPath}") 156 ctx.Strict("XZ", "${xzCmd}") 157 158 nativeHelperIncludeFlags, err := ctx.Eval("${config.CommonNativehelperInclude}") 159 if err != nil { 160 panic(err) 161 } 162 nativeHelperIncludes, nativeHelperSystemIncludes := splitSystemIncludes(ctx, nativeHelperIncludeFlags) 163 if len(nativeHelperSystemIncludes) > 0 { 164 panic("native helper may not have any system includes") 165 } 166 ctx.Strict("JNI_H_INCLUDE", strings.Join(nativeHelperIncludes, " ")) 167 168 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}") 169 if err != nil { 170 panic(err) 171 } 172 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 173 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 174 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 175 176 sort.Strings(ndkKnownLibs) 177 ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " ")) 178 179 hostTargets := ctx.Config().Targets[android.BuildOs] 180 makeVarsToolchain(ctx, "", hostTargets[0]) 181 if len(hostTargets) > 1 { 182 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 183 } 184 185 deviceTargets := ctx.Config().Targets[android.Android] 186 makeVarsToolchain(ctx, "", deviceTargets[0]) 187 if len(deviceTargets) > 1 { 188 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 189 } 190} 191 192func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, 193 target android.Target) { 194 var typePrefix string 195 switch target.Os.Class { 196 case android.Host: 197 typePrefix = "HOST_" 198 case android.Device: 199 typePrefix = "TARGET_" 200 } 201 makePrefix := secondPrefix + typePrefix 202 203 toolchain := config.FindToolchain(target.Os, target.Arch) 204 205 var productExtraCflags string 206 var productExtraLdflags string 207 208 hod := "Host" 209 if target.Os.Class == android.Device { 210 hod = "Device" 211 } 212 213 if target.Os.Class == android.Host && ctx.Config().HostStaticBinaries() { 214 productExtraLdflags += "-static" 215 } 216 217 includeFlags, err := ctx.Eval(toolchain.IncludeFlags()) 218 if err != nil { 219 panic(err) 220 } 221 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 222 ctx.StrictRaw(makePrefix+"C_INCLUDES", strings.Join(includes, " ")) 223 ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " ")) 224 225 if target.Arch.ArchType == android.Arm { 226 flags, err := toolchain.ClangInstructionSetFlags("arm") 227 if err != nil { 228 panic(err) 229 } 230 ctx.Strict(makePrefix+"arm_CFLAGS", flags) 231 232 flags, err = toolchain.ClangInstructionSetFlags("thumb") 233 if err != nil { 234 panic(err) 235 } 236 ctx.Strict(makePrefix+"thumb_CFLAGS", flags) 237 } 238 239 clangPrefix := secondPrefix + "CLANG_" + typePrefix 240 clangExtras := "-B" + config.ToolPath(toolchain) 241 242 ctx.Strict(clangPrefix+"TRIPLE", toolchain.ClangTriple()) 243 ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 244 toolchain.ClangCflags(), 245 "${config.CommonClangGlobalCflags}", 246 fmt.Sprintf("${config.%sClangGlobalCflags}", hod), 247 toolchain.ToolchainClangCflags(), 248 clangExtras, 249 productExtraCflags, 250 }, " ")) 251 ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 252 "${config.CommonClangGlobalCppflags}", 253 fmt.Sprintf("${config.%sGlobalCppflags}", hod), 254 toolchain.ClangCppflags(), 255 }, " ")) 256 ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 257 fmt.Sprintf("${config.%sGlobalLdflags}", hod), 258 toolchain.ClangLdflags(), 259 toolchain.ToolchainClangLdflags(), 260 productExtraLdflags, 261 clangExtras, 262 }, " ")) 263 ctx.Strict(clangPrefix+"GLOBAL_LLDFLAGS", strings.Join([]string{ 264 fmt.Sprintf("${config.%sGlobalLldflags}", hod), 265 toolchain.ClangLldflags(), 266 toolchain.ToolchainClangLdflags(), 267 productExtraLdflags, 268 clangExtras, 269 }, " ")) 270 271 if target.Os.Class == android.Device { 272 ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so")) 273 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerRuntimeLibrary(toolchain), ".so")) 274 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_STATIC_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerStaticLibrary(toolchain), ".a")) 275 ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so")) 276 ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a")) 277 ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so")) 278 ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so")) 279 ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so")) 280 } 281 282 // This is used by external/gentoo/... 283 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 284 toolchain.ClangTriple()) 285 286 if target.Os == android.Darwin { 287 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 288 ctx.Strict(makePrefix+"NM", "${config.MacToolPath}/nm") 289 ctx.Strict(makePrefix+"OTOOL", "${config.MacToolPath}/otool") 290 ctx.Strict(makePrefix+"STRIP", "${config.MacStripPath}") 291 } else { 292 ctx.Strict(makePrefix+"AR", "${config.ClangBin}/llvm-ar") 293 ctx.Strict(makePrefix+"READELF", gccCmd(toolchain, "readelf")) 294 ctx.Strict(makePrefix+"NM", gccCmd(toolchain, "nm")) 295 ctx.Strict(makePrefix+"STRIP", gccCmd(toolchain, "strip")) 296 } 297 298 if target.Os.Class == android.Device { 299 ctx.Strict(makePrefix+"OBJCOPY", gccCmd(toolchain, "objcopy")) 300 ctx.Strict(makePrefix+"LD", gccCmd(toolchain, "ld")) 301 ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion()) 302 ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) 303 ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, "")) 304 } 305 306 if target.Os.Class == android.Host { 307 ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " ")) 308 } 309 310 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 311 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 312} 313 314func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 315 flags, err := ctx.Eval(val) 316 if err != nil { 317 panic(err) 318 } 319 320 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 321 if strings.HasPrefix(flags, prefix) { 322 flags = strings.TrimPrefix(flags, prefix) 323 flags = strings.TrimLeft(flags, " ") 324 s := strings.SplitN(flags, " ", 2) 325 dirs = append(dirs, s[0]) 326 if len(s) > 1 { 327 return strings.TrimLeft(s[1], " "), dirs, true 328 } 329 return "", dirs, true 330 } else { 331 return flags, dirs, false 332 } 333 } 334 335 flags = strings.TrimLeft(flags, " ") 336 for flags != "" { 337 found := false 338 flags, includes, found = extract(flags, includes, "-I") 339 if !found { 340 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 341 } 342 if !found { 343 panic(fmt.Errorf("Unexpected flag in %q", flags)) 344 } 345 } 346 347 return includes, systemIncludes 348} 349 350func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 351 rets := make([]string, len(checks)) 352 for i, check := range config.DefaultLocalTidyChecks { 353 rets[i] = check.PathPrefix + ":" + check.Checks 354 } 355 return strings.Join(rets, " ") 356} 357