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 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.ClangExternalCflags}") 96 ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideClangGlobalCflags}") 97 ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "") 98 99 ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion()) 100 ctx.Strict("RECOVERY_SNAPSHOT_VERSION", ctx.DeviceConfig().RecoverySnapshotVersion()) 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 ccModule.IsVendorPublicLibrary() && 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 128 ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " ")) 129 ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ",")) 130 131 ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " ")) 132 ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " ")) 133 ctx.Strict("CFI_EXTRA_LDFLAGS", strings.Join(cfiLdflags, " ")) 134 135 ctx.Strict("INTEGER_OVERFLOW_EXTRA_CFLAGS", strings.Join(intOverflowCflags, " ")) 136 137 ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) 138 ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) 139 ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion) 140 ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion) 141 142 ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}") 143 ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks)) 144 ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}") 145 ctx.Strict("WITH_TIDY_FLAGS", "${config.TidyWithTidyFlags}") 146 147 ctx.Strict("AIDL_CPP", "${aidlCmd}") 148 ctx.Strict("ALLOWED_MANUAL_INTERFACE_PATHS", strings.Join(allowedManualInterfacePaths, " ")) 149 150 ctx.Strict("RS_GLOBAL_INCLUDES", "${config.RsGlobalIncludes}") 151 152 ctx.Strict("SOONG_STRIP_PATH", "${stripPath}") 153 ctx.Strict("XZ", "${xzCmd}") 154 ctx.Strict("CREATE_MINIDEBUGINFO", "${createMiniDebugInfo}") 155 156 includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}") 157 if err != nil { 158 panic(err) 159 } 160 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 161 ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " ")) 162 ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " ")) 163 164 ndkKnownLibs := *getNDKKnownLibs(ctx.Config()) 165 sort.Strings(ndkKnownLibs) 166 ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " ")) 167 168 hostTargets := ctx.Config().Targets[android.BuildOs] 169 makeVarsToolchain(ctx, "", hostTargets[0]) 170 if len(hostTargets) > 1 { 171 makeVarsToolchain(ctx, "2ND_", hostTargets[1]) 172 } 173 174 deviceTargets := ctx.Config().Targets[android.Android] 175 makeVarsToolchain(ctx, "", deviceTargets[0]) 176 if len(deviceTargets) > 1 { 177 makeVarsToolchain(ctx, "2ND_", deviceTargets[1]) 178 } 179} 180 181func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, 182 target android.Target) { 183 var typePrefix string 184 switch target.Os.Class { 185 case android.Host: 186 typePrefix = "HOST_" 187 case android.Device: 188 typePrefix = "TARGET_" 189 } 190 makePrefix := secondPrefix + typePrefix 191 192 toolchain := config.FindToolchain(target.Os, target.Arch) 193 194 var productExtraCflags string 195 var productExtraLdflags string 196 197 hod := "Host" 198 if target.Os.Class == android.Device { 199 hod = "Device" 200 } 201 202 if target.Os.Class == android.Host && ctx.Config().HostStaticBinaries() { 203 productExtraLdflags += "-static" 204 } 205 206 includeFlags, err := ctx.Eval(toolchain.IncludeFlags()) 207 if err != nil { 208 panic(err) 209 } 210 includes, systemIncludes := splitSystemIncludes(ctx, includeFlags) 211 ctx.StrictRaw(makePrefix+"C_INCLUDES", strings.Join(includes, " ")) 212 ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " ")) 213 214 if target.Arch.ArchType == android.Arm { 215 flags, err := toolchain.ClangInstructionSetFlags("arm") 216 if err != nil { 217 panic(err) 218 } 219 ctx.Strict(makePrefix+"arm_CFLAGS", flags) 220 221 flags, err = toolchain.ClangInstructionSetFlags("thumb") 222 if err != nil { 223 panic(err) 224 } 225 ctx.Strict(makePrefix+"thumb_CFLAGS", flags) 226 } 227 228 clangPrefix := secondPrefix + "CLANG_" + typePrefix 229 clangExtras := "-B" + config.ToolPath(toolchain) 230 231 ctx.Strict(clangPrefix+"TRIPLE", toolchain.ClangTriple()) 232 ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{ 233 toolchain.ClangCflags(), 234 "${config.CommonClangGlobalCflags}", 235 fmt.Sprintf("${config.%sClangGlobalCflags}", hod), 236 toolchain.ToolchainClangCflags(), 237 clangExtras, 238 productExtraCflags, 239 }, " ")) 240 ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{ 241 "${config.CommonClangGlobalCppflags}", 242 fmt.Sprintf("${config.%sGlobalCppflags}", hod), 243 toolchain.ClangCppflags(), 244 }, " ")) 245 ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{ 246 fmt.Sprintf("${config.%sGlobalLdflags}", hod), 247 toolchain.ClangLdflags(), 248 toolchain.ToolchainClangLdflags(), 249 productExtraLdflags, 250 clangExtras, 251 }, " ")) 252 ctx.Strict(clangPrefix+"GLOBAL_LLDFLAGS", strings.Join([]string{ 253 fmt.Sprintf("${config.%sGlobalLldflags}", hod), 254 toolchain.ClangLldflags(), 255 toolchain.ToolchainClangLdflags(), 256 productExtraLdflags, 257 clangExtras, 258 }, " ")) 259 260 if target.Os.Class == android.Device { 261 ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so")) 262 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerRuntimeLibrary(toolchain), ".so")) 263 ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_STATIC_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerStaticLibrary(toolchain), ".a")) 264 ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so")) 265 ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a")) 266 ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so")) 267 ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so")) 268 ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so")) 269 } 270 271 // This is used by external/gentoo/... 272 ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE", 273 toolchain.ClangTriple()) 274 275 if target.Os == android.Darwin { 276 ctx.Strict(makePrefix+"AR", "${config.MacArPath}") 277 ctx.Strict(makePrefix+"NM", "${config.MacToolPath}/nm") 278 ctx.Strict(makePrefix+"OTOOL", "${config.MacToolPath}/otool") 279 ctx.Strict(makePrefix+"STRIP", "${config.MacStripPath}") 280 } else { 281 ctx.Strict(makePrefix+"AR", "${config.ClangBin}/llvm-ar") 282 ctx.Strict(makePrefix+"READELF", "${config.ClangBin}/llvm-readelf") 283 ctx.Strict(makePrefix+"NM", "${config.ClangBin}/llvm-nm") 284 ctx.Strict(makePrefix+"STRIP", "${config.ClangBin}/llvm-strip") 285 } 286 287 if target.Os.Class == android.Device { 288 ctx.Strict(makePrefix+"OBJCOPY", "${config.ClangBin}/llvm-objcopy") 289 ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld") 290 ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) 291 // TODO: work out whether to make this "${config.ClangBin}/llvm-", which 292 // should mostly work, or remove it. 293 ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, "")) 294 // TODO: GCC version is obsolete now that GCC has been removed. 295 ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion()) 296 } 297 298 if target.Os.Class == android.Host { 299 ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " ")) 300 } 301 302 ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix()) 303 ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix()) 304} 305 306func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) { 307 flags, err := ctx.Eval(val) 308 if err != nil { 309 panic(err) 310 } 311 312 extract := func(flags string, dirs []string, prefix string) (string, []string, bool) { 313 if strings.HasPrefix(flags, prefix) { 314 flags = strings.TrimPrefix(flags, prefix) 315 flags = strings.TrimLeft(flags, " ") 316 s := strings.SplitN(flags, " ", 2) 317 dirs = append(dirs, s[0]) 318 if len(s) > 1 { 319 return strings.TrimLeft(s[1], " "), dirs, true 320 } 321 return "", dirs, true 322 } else { 323 return flags, dirs, false 324 } 325 } 326 327 flags = strings.TrimLeft(flags, " ") 328 for flags != "" { 329 found := false 330 flags, includes, found = extract(flags, includes, "-I") 331 if !found { 332 flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ") 333 } 334 if !found { 335 panic(fmt.Errorf("Unexpected flag in %q", flags)) 336 } 337 } 338 339 return includes, systemIncludes 340} 341 342func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string { 343 rets := make([]string, len(checks)) 344 for i, check := range config.DefaultLocalTidyChecks { 345 rets[i] = check.PathPrefix + ":" + check.Checks 346 } 347 return strings.Join(rets, " ") 348} 349