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 ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " ")) 101 102 ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion()) 103 104 // Filter vendor_public_library that are exported to make 105 exportedVendorPublicLibraries := []string{} 106 ctx.VisitAllModules(func(module android.Module) { 107 if ccModule, ok := module.(*Module); ok { 108 baseName := ccModule.BaseModuleName() 109 if inList(baseName, *vendorPublicLibraries) && module.ExportedToMake() { 110 if !inList(baseName, exportedVendorPublicLibraries) { 111 exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName) 112 } 113 } 114 } 115 }) 116 sort.Strings(exportedVendorPublicLibraries) 117 ctx.Strict("VENDOR_PUBLIC_LIBRARIES", strings.Join(exportedVendorPublicLibraries, " ")) 118 119 sort.Strings(lsdumpPaths) 120 ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " ")) 121 122 ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects()) 123 ctx.Strict("SOONG_MODULES_ADDED_WALL", makeStringOfKeys(ctx, modulesAddedWallKey)) 124 ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeStringOfKeys(ctx, modulesUsingWnoErrorKey)) 125 ctx.Strict("SOONG_MODULES_MISSING_PGO_PROFILE_FILE", makeStringOfKeys(ctx, modulesMissingProfileFileKey)) 126 127 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " ")) 128 ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " ")) 129 130 ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " ")) 131 ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ",")) 132 133 ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " ")) 134 ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " ")) 135 ctx.Strict("CFI_EXTRA_LDFLAGS", strings.Join(cfiLdflags, " ")) 136 137 ctx.Strict("INTEGER_OVERFLOW_EXTRA_CFLAGS", strings.Join(intOverflowCflags, " ")) 138 139 ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) 140 ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) 141 ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion) 142 ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion) 143 144 ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}") 145 ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks)) 146 ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}") 147 ctx.Strict("WITH_TIDY_FLAGS", "${config.TidyWithTidyFlags}") 148 149 ctx.Strict("AIDL_CPP", "${aidlCmd}") 150 ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " ")) 151 152 ctx.Strict("M4", "${m4Cmd}") 153 154 ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") 155 156 ctx.Strict("SOONG_STRIP_PATH", "${stripPath}") 157 ctx.Strict("XZ", "${xzCmd}") 158 159 nativeHelperIncludeFlags, err := ctx.Eval("${config.CommonNativehelperInclude}") 160 if err != nil { 161 panic(err) 162 } 163 nativeHelperIncludes, nativeHelperSystemIncludes := splitSystemIncludes(ctx, nativeHelperIncludeFlags) 164 if len(nativeHelperSystemIncludes) > 0 { 165 panic("native helper may not have any system includes") 166 } 167 ctx.Strict("JNI_H_INCLUDE", strings.Join(nativeHelperIncludes, " ")) 168 169 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}") 170 if err != nil { 171 panic(err) 172 } 173 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 174 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 175 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 176 177 sort.Strings(ndkMigratedLibs) 178 ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " ")) 179 180 hostTargets := ctx.Config().Targets[android.BuildOs] 181 makeVarsToolchain(ctx, "", hostTargets[0]) 182 if len(hostTargets) > 1 { 183 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 184 } 185 186 deviceTargets := ctx.Config().Targets[android.Android] 187 makeVarsToolchain(ctx, "", deviceTargets[0]) 188 if len(deviceTargets) > 1 { 189 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 190 } 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.ClangInstructionSetFlags("arm") 228 if err != nil { 229 panic(err) 230 } 231 ctx.Strict(makePrefix+"arm_CFLAGS", flags) 232 233 flags, err = toolchain.ClangInstructionSetFlags("thumb") 234 if err != nil { 235 panic(err) 236 } 237 ctx.Strict(makePrefix+"thumb_CFLAGS", flags) 238 } 239 240 clangPrefix := secondPrefix + "CLANG_" + typePrefix 241 clangExtras := "-B" + config.ToolPath(toolchain) 242 243 ctx.Strict(clangPrefix+"TRIPLE", toolchain.ClangTriple()) 244 ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 245 toolchain.ClangCflags(), 246 "${config.CommonClangGlobalCflags}", 247 fmt.Sprintf("${config.%sClangGlobalCflags}", hod), 248 toolchain.ToolchainClangCflags(), 249 clangExtras, 250 productExtraCflags, 251 }, " ")) 252 ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 253 "${config.CommonClangGlobalCppflags}", 254 fmt.Sprintf("${config.%sGlobalCppflags}", hod), 255 toolchain.ClangCppflags(), 256 }, " ")) 257 ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 258 fmt.Sprintf("${config.%sGlobalLdflags}", hod), 259 toolchain.ClangLdflags(), 260 toolchain.ToolchainClangLdflags(), 261 productExtraLdflags, 262 clangExtras, 263 }, " ")) 264 ctx.Strict(clangPrefix+"GLOBAL_LLDFLAGS", strings.Join([]string{ 265 fmt.Sprintf("${config.%sGlobalLldflags}", hod), 266 toolchain.ClangLldflags(), 267 toolchain.ToolchainClangLdflags(), 268 productExtraLdflags, 269 clangExtras, 270 }, " ")) 271 272 if target.Os.Class == android.Device { 273 ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so")) 274 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerRuntimeLibrary(toolchain), ".so")) 275 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_STATIC_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerStaticLibrary(toolchain), ".a")) 276 ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so")) 277 ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a")) 278 ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so")) 279 ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so")) 280 ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so")) 281 } 282 283 // This is used by external/gentoo/... 284 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 285 toolchain.ClangTriple()) 286 287 if target.Os == android.Darwin { 288 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 289 ctx.Strict(makePrefix+"NM", "${config.MacToolPath}/nm") 290 ctx.Strict(makePrefix+"OTOOL", "${config.MacToolPath}/otool") 291 ctx.Strict(makePrefix+"STRIP", "${config.MacStripPath}") 292 } else { 293 ctx.Strict(makePrefix+"AR", "${config.ClangBin}/llvm-ar") 294 ctx.Strict(makePrefix+"READELF", gccCmd(toolchain, "readelf")) 295 ctx.Strict(makePrefix+"NM", gccCmd(toolchain, "nm")) 296 ctx.Strict(makePrefix+"STRIP", gccCmd(toolchain, "strip")) 297 } 298 299 if target.Os.Class == android.Device { 300 ctx.Strict(makePrefix+"OBJCOPY", gccCmd(toolchain, "objcopy")) 301 ctx.Strict(makePrefix+"LD", gccCmd(toolchain, "ld")) 302 ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion()) 303 ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) 304 ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, "")) 305 } 306 307 if target.Os.Class == android.Host { 308 ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " ")) 309 } 310 311 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 312 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 313} 314 315func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 316 flags, err := ctx.Eval(val) 317 if err != nil { 318 panic(err) 319 } 320 321 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 322 if strings.HasPrefix(flags, prefix) { 323 flags = strings.TrimPrefix(flags, prefix) 324 flags = strings.TrimLeft(flags, " ") 325 s := strings.SplitN(flags, " ", 2) 326 dirs = append(dirs, s[0]) 327 if len(s) > 1 { 328 return strings.TrimLeft(s[1], " "), dirs, true 329 } 330 return "", dirs, true 331 } else { 332 return flags, dirs, false 333 } 334 } 335 336 flags = strings.TrimLeft(flags, " ") 337 for flags != "" { 338 found := false 339 flags, includes, found = extract(flags, includes, "-I") 340 if !found { 341 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 342 } 343 if !found { 344 panic(fmt.Errorf("Unexpected flag in %q", flags)) 345 } 346 } 347 348 return includes, systemIncludes 349} 350 351func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 352 rets := make([]string, len(checks)) 353 for i, check := range config.DefaultLocalTidyChecks { 354 rets[i] = check.PathPrefix + ":" + check.Checks 355 } 356 return strings.Join(rets, " ") 357} 358