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