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 "path/filepath" 20 "strings" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/cc/config" 26) 27 28// This file contains the basic C/C++/assembly to .o compliation steps 29 30type BaseCompilerProperties struct { 31 // list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files. 32 // srcs may reference the outputs of other modules that produce source files like genrule 33 // or filegroup using the syntax ":module". 34 Srcs []string `android:"path,arch_variant"` 35 36 // list of source files that should not be used to build the C/C++ module. 37 // This is most useful in the arch/multilib variants to remove non-common files 38 Exclude_srcs []string `android:"path,arch_variant"` 39 40 // list of module-specific flags that will be used for C and C++ compiles. 41 Cflags []string `android:"arch_variant"` 42 43 // list of module-specific flags that will be used for C++ compiles 44 Cppflags []string `android:"arch_variant"` 45 46 // list of module-specific flags that will be used for C compiles 47 Conlyflags []string `android:"arch_variant"` 48 49 // list of module-specific flags that will be used for .S compiles 50 Asflags []string `android:"arch_variant"` 51 52 // list of module-specific flags that will be used for C and C++ compiles when 53 // compiling with clang 54 Clang_cflags []string `android:"arch_variant"` 55 56 // list of module-specific flags that will be used for .S compiles when 57 // compiling with clang 58 Clang_asflags []string `android:"arch_variant"` 59 60 // list of module-specific flags that will be used for .y and .yy compiles 61 Yaccflags []string 62 63 // the instruction set architecture to use to compile the C/C++ 64 // module. 65 Instruction_set *string `android:"arch_variant"` 66 67 // list of directories relative to the root of the source tree that will 68 // be added to the include path using -I. 69 // If possible, don't use this. If adding paths from the current directory use 70 // local_include_dirs, if adding paths from other modules use export_include_dirs in 71 // that module. 72 Include_dirs []string `android:"arch_variant,variant_prepend"` 73 74 // list of directories relative to the Blueprints file that will 75 // be added to the include path using -I 76 Local_include_dirs []string `android:"arch_variant,variant_prepend"` 77 78 // Add the directory containing the Android.bp file to the list of include 79 // directories. Defaults to true. 80 Include_build_directory *bool 81 82 // list of generated sources to compile. These are the names of gensrcs or 83 // genrule modules. 84 Generated_sources []string `android:"arch_variant"` 85 86 // list of generated headers to add to the include path. These are the names 87 // of genrule modules. 88 Generated_headers []string `android:"arch_variant"` 89 90 // pass -frtti instead of -fno-rtti 91 Rtti *bool 92 93 // C standard version to use. Can be a specific version (such as "gnu11"), 94 // "experimental" (which will use draft versions like C1x when available), 95 // or the empty string (which will use the default). 96 C_std *string 97 98 // C++ standard version to use. Can be a specific version (such as 99 // "gnu++11"), "experimental" (which will use draft versions like C++1z when 100 // available), or the empty string (which will use the default). 101 Cpp_std *string 102 103 // if set to false, use -std=c++* instead of -std=gnu++* 104 Gnu_extensions *bool 105 106 Aidl struct { 107 // list of directories that will be added to the aidl include paths. 108 Include_dirs []string 109 110 // list of directories relative to the Blueprints file that will 111 // be added to the aidl include paths. 112 Local_include_dirs []string 113 114 // whether to generate traces (for systrace) for this interface 115 Generate_traces *bool 116 } 117 118 Renderscript struct { 119 // list of directories that will be added to the llvm-rs-cc include paths 120 Include_dirs []string 121 122 // list of flags that will be passed to llvm-rs-cc 123 Flags []string 124 125 // Renderscript API level to target 126 Target_api *string 127 } 128 129 Debug, Release struct { 130 // list of module-specific flags that will be used for C and C++ compiles in debug or 131 // release builds 132 Cflags []string `android:"arch_variant"` 133 } `android:"arch_variant"` 134 135 Target struct { 136 Vendor struct { 137 // list of source files that should only be used in the 138 // vendor variant of the C/C++ module. 139 Srcs []string `android:"path"` 140 141 // list of source files that should not be used to 142 // build the vendor variant of the C/C++ module. 143 Exclude_srcs []string `android:"path"` 144 145 // List of additional cflags that should be used to build the vendor 146 // variant of the C/C++ module. 147 Cflags []string 148 } 149 Recovery struct { 150 // list of source files that should only be used in the 151 // recovery variant of the C/C++ module. 152 Srcs []string `android:"path"` 153 154 // list of source files that should not be used to 155 // build the recovery variant of the C/C++ module. 156 Exclude_srcs []string `android:"path"` 157 158 // List of additional cflags that should be used to build the recovery 159 // variant of the C/C++ module. 160 Cflags []string 161 } 162 } 163 164 Proto struct { 165 // Link statically against the protobuf runtime 166 Static *bool `android:"arch_variant"` 167 } `android:"arch_variant"` 168 169 // Stores the original list of source files before being cleared by library reuse 170 OriginalSrcs []string `blueprint:"mutated"` 171 172 // Build and link with OpenMP 173 Openmp *bool `android:"arch_variant"` 174} 175 176func NewBaseCompiler() *baseCompiler { 177 return &baseCompiler{} 178} 179 180type baseCompiler struct { 181 Properties BaseCompilerProperties 182 Proto android.ProtoProperties 183 cFlagsDeps android.Paths 184 pathDeps android.Paths 185 flags builderFlags 186 187 // Sources that were passed to the C/C++ compiler 188 srcs android.Paths 189 190 // Sources that were passed in the Android.bp file, including generated sources generated by 191 // other modules and filegroups. May include source files that have not yet been translated to 192 // C/C++ (.aidl, .proto, etc.) 193 srcsBeforeGen android.Paths 194} 195 196var _ compiler = (*baseCompiler)(nil) 197 198type CompiledInterface interface { 199 Srcs() android.Paths 200} 201 202func (compiler *baseCompiler) Srcs() android.Paths { 203 return append(android.Paths{}, compiler.srcs...) 204} 205 206func (compiler *baseCompiler) appendCflags(flags []string) { 207 compiler.Properties.Cflags = append(compiler.Properties.Cflags, flags...) 208} 209 210func (compiler *baseCompiler) appendAsflags(flags []string) { 211 compiler.Properties.Asflags = append(compiler.Properties.Asflags, flags...) 212} 213 214func (compiler *baseCompiler) compilerProps() []interface{} { 215 return []interface{}{&compiler.Properties, &compiler.Proto} 216} 217 218func (compiler *baseCompiler) compilerInit(ctx BaseModuleContext) {} 219 220func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { 221 deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...) 222 deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...) 223 224 android.ProtoDeps(ctx, &compiler.Proto) 225 if compiler.hasSrcExt(".proto") { 226 deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static)) 227 } 228 229 if compiler.hasSrcExt(".sysprop") { 230 deps.HeaderLibs = append(deps.HeaderLibs, "libbase_headers") 231 deps.SharedLibs = append(deps.SharedLibs, "liblog") 232 } 233 234 if Bool(compiler.Properties.Openmp) { 235 deps.StaticLibs = append(deps.StaticLibs, "libomp") 236 } 237 238 return deps 239} 240 241// Return true if the module is in the WarningAllowedProjects. 242func warningsAreAllowed(subdir string) bool { 243 subdir += "/" 244 for _, prefix := range config.WarningAllowedProjects { 245 if strings.HasPrefix(subdir, prefix) { 246 return true 247 } 248 } 249 return false 250} 251 252func addToModuleList(ctx ModuleContext, key android.OnceKey, module string) { 253 getNamedMapForConfig(ctx.Config(), key).Store(module, true) 254} 255 256// Create a Flags struct that collects the compile flags from global values, 257// per-target values, module type values, and per-module Blueprints properties 258func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags { 259 tc := ctx.toolchain() 260 261 compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs) 262 compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...) 263 264 CheckBadCompilerFlags(ctx, "cflags", compiler.Properties.Cflags) 265 CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags) 266 CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags) 267 CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags) 268 CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags) 269 CheckBadCompilerFlags(ctx, "recovery.cflags", compiler.Properties.Target.Recovery.Cflags) 270 271 esc := proptools.NinjaAndShellEscapeList 272 273 flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Cflags)...) 274 flags.CppFlags = append(flags.CppFlags, esc(compiler.Properties.Cppflags)...) 275 flags.ConlyFlags = append(flags.ConlyFlags, esc(compiler.Properties.Conlyflags)...) 276 flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Asflags)...) 277 flags.YasmFlags = append(flags.YasmFlags, esc(compiler.Properties.Asflags)...) 278 flags.YaccFlags = append(flags.YaccFlags, esc(compiler.Properties.Yaccflags)...) 279 280 // Include dir cflags 281 localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs) 282 if len(localIncludeDirs) > 0 { 283 f := includeDirsToFlags(localIncludeDirs) 284 flags.GlobalFlags = append(flags.GlobalFlags, f) 285 flags.YasmFlags = append(flags.YasmFlags, f) 286 } 287 rootIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Include_dirs) 288 if len(rootIncludeDirs) > 0 { 289 f := includeDirsToFlags(rootIncludeDirs) 290 flags.GlobalFlags = append(flags.GlobalFlags, f) 291 flags.YasmFlags = append(flags.YasmFlags, f) 292 } 293 294 if compiler.Properties.Include_build_directory == nil || 295 *compiler.Properties.Include_build_directory { 296 flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String()) 297 flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String()) 298 } 299 300 if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() { 301 flags.SystemIncludeFlags = append(flags.SystemIncludeFlags, 302 "${config.CommonGlobalIncludes}", 303 tc.IncludeFlags(), 304 "${config.CommonNativehelperInclude}") 305 } 306 307 if ctx.useSdk() { 308 // TODO: Switch to --sysroot. 309 // The NDK headers are installed to a common sysroot. While a more 310 // typical Soong approach would be to only make the headers for the 311 // library you're using available, we're trying to emulate the NDK 312 // behavior here, and the NDK always has all the NDK headers available. 313 flags.SystemIncludeFlags = append(flags.SystemIncludeFlags, 314 "-isystem "+getCurrentIncludePath(ctx).String(), 315 "-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String()) 316 317 // TODO: Migrate to API suffixed triple? 318 // Traditionally this has come from android/api-level.h, but with the 319 // libc headers unified it must be set by the build system since we 320 // don't have per-API level copies of that header now. 321 version := ctx.sdkVersion() 322 if version == "current" { 323 version = "__ANDROID_API_FUTURE__" 324 } 325 flags.GlobalFlags = append(flags.GlobalFlags, 326 "-D__ANDROID_API__="+version) 327 } 328 329 if ctx.useVndk() { 330 // sdkVersion() returns VNDK version for vendor modules. 331 version := ctx.sdkVersion() 332 if version == "current" { 333 version = "__ANDROID_API_FUTURE__" 334 } 335 flags.GlobalFlags = append(flags.GlobalFlags, 336 "-D__ANDROID_API__="+version, "-D__ANDROID_VNDK__") 337 } 338 339 if ctx.inRecovery() { 340 flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_RECOVERY__") 341 } 342 343 if ctx.apexName() != "" { 344 flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__="+ctx.apexName()) 345 } 346 347 instructionSet := String(compiler.Properties.Instruction_set) 348 if flags.RequiredInstructionSet != "" { 349 instructionSet = flags.RequiredInstructionSet 350 } 351 instructionSetFlags, err := tc.ClangInstructionSetFlags(instructionSet) 352 if err != nil { 353 ctx.ModuleErrorf("%s", err) 354 } 355 356 CheckBadCompilerFlags(ctx, "release.cflags", compiler.Properties.Release.Cflags) 357 358 // TODO: debug 359 flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Release.Cflags)...) 360 361 CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags) 362 CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags) 363 364 flags.CFlags = config.ClangFilterUnknownCflags(flags.CFlags) 365 flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Clang_cflags)...) 366 flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Clang_asflags)...) 367 flags.CppFlags = config.ClangFilterUnknownCflags(flags.CppFlags) 368 flags.ConlyFlags = config.ClangFilterUnknownCflags(flags.ConlyFlags) 369 flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags) 370 371 target := "-target " + tc.ClangTriple() 372 gccPrefix := "-B" + config.ToolPath(tc) 373 374 flags.CFlags = append(flags.CFlags, target, gccPrefix) 375 flags.AsFlags = append(flags.AsFlags, target, gccPrefix) 376 flags.LdFlags = append(flags.LdFlags, target, gccPrefix) 377 378 hod := "Host" 379 if ctx.Os().Class == android.Device { 380 hod = "Device" 381 } 382 383 flags.GlobalFlags = append(flags.GlobalFlags, instructionSetFlags) 384 flags.ConlyFlags = append([]string{"${config.CommonGlobalConlyflags}"}, flags.ConlyFlags...) 385 flags.CppFlags = append([]string{fmt.Sprintf("${config.%sGlobalCppflags}", hod)}, flags.CppFlags...) 386 387 flags.AsFlags = append(flags.AsFlags, tc.ClangAsflags()) 388 flags.CppFlags = append([]string{"${config.CommonClangGlobalCppflags}"}, flags.CppFlags...) 389 flags.GlobalFlags = append(flags.GlobalFlags, 390 tc.ClangCflags(), 391 "${config.CommonClangGlobalCflags}", 392 fmt.Sprintf("${config.%sClangGlobalCflags}", hod)) 393 394 if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") { 395 flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...) 396 } 397 398 if tc.Bionic() { 399 if Bool(compiler.Properties.Rtti) { 400 flags.CppFlags = append(flags.CppFlags, "-frtti") 401 } else { 402 flags.CppFlags = append(flags.CppFlags, "-fno-rtti") 403 } 404 } 405 406 flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__") 407 408 flags.CppFlags = append(flags.CppFlags, tc.ClangCppflags()) 409 410 flags.YasmFlags = append(flags.YasmFlags, tc.YasmFlags()) 411 412 flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainClangCflags()) 413 414 cStd := config.CStdVersion 415 if String(compiler.Properties.C_std) == "experimental" { 416 cStd = config.ExperimentalCStdVersion 417 } else if String(compiler.Properties.C_std) != "" { 418 cStd = String(compiler.Properties.C_std) 419 } 420 421 cppStd := String(compiler.Properties.Cpp_std) 422 switch String(compiler.Properties.Cpp_std) { 423 case "": 424 cppStd = config.CppStdVersion 425 case "experimental": 426 cppStd = config.ExperimentalCppStdVersion 427 } 428 429 if compiler.Properties.Gnu_extensions != nil && *compiler.Properties.Gnu_extensions == false { 430 cStd = gnuToCReplacer.Replace(cStd) 431 cppStd = gnuToCReplacer.Replace(cppStd) 432 } 433 434 flags.ConlyFlags = append([]string{"-std=" + cStd}, flags.ConlyFlags...) 435 flags.CppFlags = append([]string{"-std=" + cppStd}, flags.CppFlags...) 436 437 if ctx.useVndk() { 438 flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Target.Vendor.Cflags)...) 439 } 440 441 if ctx.inRecovery() { 442 flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Target.Recovery.Cflags)...) 443 } 444 445 // We can enforce some rules more strictly in the code we own. strict 446 // indicates if this is code that we can be stricter with. If we have 447 // rules that we want to apply to *our* code (but maybe can't for 448 // vendor/device specific things), we could extend this to be a ternary 449 // value. 450 strict := true 451 if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") { 452 strict = false 453 } 454 455 // Can be used to make some annotations stricter for code we can fix 456 // (such as when we mark functions as deprecated). 457 if strict { 458 flags.CFlags = append(flags.CFlags, "-DANDROID_STRICT") 459 } 460 461 if compiler.hasSrcExt(".proto") { 462 flags = protoFlags(ctx, flags, &compiler.Proto) 463 } 464 465 if compiler.hasSrcExt(".y") || compiler.hasSrcExt(".yy") { 466 flags.GlobalFlags = append(flags.GlobalFlags, 467 "-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String()) 468 } 469 470 if compiler.hasSrcExt(".mc") { 471 flags.GlobalFlags = append(flags.GlobalFlags, 472 "-I"+android.PathForModuleGen(ctx, "windmc", ctx.ModuleDir()).String()) 473 } 474 475 if compiler.hasSrcExt(".aidl") { 476 if len(compiler.Properties.Aidl.Local_include_dirs) > 0 { 477 localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs) 478 flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(localAidlIncludeDirs)) 479 } 480 if len(compiler.Properties.Aidl.Include_dirs) > 0 { 481 rootAidlIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Aidl.Include_dirs) 482 flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs)) 483 } 484 485 if Bool(compiler.Properties.Aidl.Generate_traces) { 486 flags.aidlFlags = append(flags.aidlFlags, "-t") 487 } 488 489 flags.GlobalFlags = append(flags.GlobalFlags, 490 "-I"+android.PathForModuleGen(ctx, "aidl").String()) 491 } 492 493 if compiler.hasSrcExt(".rs") || compiler.hasSrcExt(".fs") { 494 flags = rsFlags(ctx, flags, &compiler.Properties) 495 } 496 497 if compiler.hasSrcExt(".sysprop") { 498 flags.GlobalFlags = append(flags.GlobalFlags, 499 "-I"+android.PathForModuleGen(ctx, "sysprop", "include").String()) 500 } 501 502 if len(compiler.Properties.Srcs) > 0 { 503 module := ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName() 504 if inList("-Wno-error", flags.CFlags) || inList("-Wno-error", flags.CppFlags) { 505 addToModuleList(ctx, modulesUsingWnoErrorKey, module) 506 } else if !inList("-Werror", flags.CFlags) && !inList("-Werror", flags.CppFlags) { 507 if warningsAreAllowed(ctx.ModuleDir()) { 508 addToModuleList(ctx, modulesAddedWallKey, module) 509 flags.CFlags = append([]string{"-Wall"}, flags.CFlags...) 510 } else { 511 flags.CFlags = append([]string{"-Wall", "-Werror"}, flags.CFlags...) 512 } 513 } 514 } 515 516 if Bool(compiler.Properties.Openmp) { 517 flags.CFlags = append(flags.CFlags, "-fopenmp") 518 } 519 520 return flags 521} 522 523func (compiler *baseCompiler) hasSrcExt(ext string) bool { 524 for _, src := range compiler.srcsBeforeGen { 525 if src.Ext() == ext { 526 return true 527 } 528 } 529 for _, src := range compiler.Properties.Srcs { 530 if filepath.Ext(src) == ext { 531 return true 532 } 533 } 534 for _, src := range compiler.Properties.OriginalSrcs { 535 if filepath.Ext(src) == ext { 536 return true 537 } 538 } 539 540 return false 541} 542 543var gnuToCReplacer = strings.NewReplacer("gnu", "c") 544 545func ndkPathDeps(ctx ModuleContext) android.Paths { 546 if ctx.useSdk() { 547 // The NDK sysroot timestamp file depends on all the NDK sysroot files 548 // (headers and libraries). 549 return android.Paths{getNdkBaseTimestampFile(ctx)} 550 } 551 return nil 552} 553 554func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects { 555 pathDeps := deps.GeneratedHeaders 556 pathDeps = append(pathDeps, ndkPathDeps(ctx)...) 557 558 buildFlags := flagsToBuilderFlags(flags) 559 560 srcs := append(android.Paths(nil), compiler.srcsBeforeGen...) 561 562 srcs, genDeps := genSources(ctx, srcs, buildFlags) 563 pathDeps = append(pathDeps, genDeps...) 564 565 compiler.pathDeps = pathDeps 566 compiler.cFlagsDeps = flags.CFlagsDeps 567 568 // Save src, buildFlags and context 569 compiler.srcs = srcs 570 571 // Compile files listed in c.Properties.Srcs into objects 572 objs := compileObjs(ctx, buildFlags, "", srcs, pathDeps, compiler.cFlagsDeps) 573 574 if ctx.Failed() { 575 return Objects{} 576 } 577 578 return objs 579} 580 581// Compile a list of source files into objects a specified subdirectory 582func compileObjs(ctx android.ModuleContext, flags builderFlags, 583 subdir string, srcFiles, pathDeps android.Paths, cFlagsDeps android.Paths) Objects { 584 585 return TransformSourceToObj(ctx, subdir, srcFiles, flags, pathDeps, cFlagsDeps) 586} 587