blob: 0b595ecb66b1c88f691e4edfb1b5894ebe1c1263 [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001//
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package cc
15
16// This file contains the module types for compiling C/C++ for Android, and converts the properties
17// into the flags and filenames necessary to pass to the compiler. The final creation of the rules
18// is handled in builder.go
19
20import (
21 "blueprint"
22 "blueprint/pathtools"
23 "fmt"
24 "path/filepath"
25 "strings"
26
27 "android/soong/common"
28)
29
30type Config interface {
31 SrcDir() string
32 PrebuiltOS() string
33}
34
35var (
36 HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", Config.PrebuiltOS)
37 SrcDir = pctx.VariableConfigMethod("SrcDir", Config.SrcDir)
38
39 LibcRoot = pctx.StaticVariable("LibcRoot", "${SrcDir}/bionic/libc")
40 LibmRoot = pctx.StaticVariable("LibmRoot", "${SrcDir}/bionic/libm")
41)
42
43// Flags used by lots of devices. Putting them in package static variables will save bytes in
44// build.ninja so they aren't repeated for every file
45var (
46 commonGlobalCflags = []string{
47 "-DANDROID",
48 "-fmessage-length=0",
49 "-W",
50 "-Wall",
51 "-Wno-unused",
52 "-Winit-self",
53 "-Wpointer-arith",
54
55 // COMMON_RELEASE_CFLAGS
56 "-DNDEBUG",
57 "-UDEBUG",
58 }
59
60 deviceGlobalCflags = []string{
61 // TARGET_ERROR_FLAGS
62 "-Werror=return-type",
63 "-Werror=non-virtual-dtor",
64 "-Werror=address",
65 "-Werror=sequence-point",
66 }
67
68 hostGlobalCflags = []string{}
69
70 commonGlobalCppflags = []string{
71 "-Wsign-promo",
72 "-std=gnu++11",
73 }
74)
75
76func init() {
77 pctx.StaticVariable("commonGlobalCflags", strings.Join(commonGlobalCflags, " "))
78 pctx.StaticVariable("deviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
79 pctx.StaticVariable("hostGlobalCflags", strings.Join(hostGlobalCflags, " "))
80
81 pctx.StaticVariable("commonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
82
83 pctx.StaticVariable("commonClangGlobalCflags",
84 strings.Join(clangFilterUnknownCflags(commonGlobalCflags), " "))
85 pctx.StaticVariable("deviceClangGlobalCflags",
86 strings.Join(clangFilterUnknownCflags(deviceGlobalCflags), " "))
87 pctx.StaticVariable("hostClangGlobalCflags",
88 strings.Join(clangFilterUnknownCflags(hostGlobalCflags), " "))
Tim Kilbournf2948142015-03-11 12:03:03 -070089 pctx.StaticVariable("commonClangGlobalCppflags",
90 strings.Join(clangFilterUnknownCflags(commonGlobalCppflags), " "))
Colin Cross3f40fa42015-01-30 17:27:36 -080091
92 // Everything in this list is a crime against abstraction and dependency tracking.
93 // Do not add anything to this list.
94 pctx.StaticVariable("commonGlobalIncludes", strings.Join([]string{
95 "-isystem ${SrcDir}/system/core/include",
96 "-isystem ${SrcDir}/hardware/libhardware/include",
97 "-isystem ${SrcDir}/hardware/libhardware_legacy/include",
98 "-isystem ${SrcDir}/hardware/ril/include",
99 "-isystem ${SrcDir}/libnativehelper/include",
100 "-isystem ${SrcDir}/frameworks/native/include",
101 "-isystem ${SrcDir}/frameworks/native/opengl/include",
102 "-isystem ${SrcDir}/frameworks/av/include",
103 "-isystem ${SrcDir}/frameworks/base/include",
104 }, " "))
105
106 pctx.StaticVariable("clangPath", "${SrcDir}/prebuilts/clang/${HostPrebuiltTag}/host/3.6/bin/")
107}
108
109// CcProperties describes properties used to compile all C or C++ modules
110type ccProperties struct {
111 // srcs: list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files.
112 Srcs []string `android:"arch_variant,arch_subtract"`
113
114 // cflags: list of module-specific flags that will be used for C and C++ compiles.
115 Cflags []string `android:"arch_variant"`
116
117 // cppflags: list of module-specific flags that will be used for C++ compiles
118 Cppflags []string `android:"arch_variant"`
119
120 // conlyflags: list of module-specific flags that will be used for C compiles
121 Conlyflags []string `android:"arch_variant"`
122
123 // asflags: list of module-specific flags that will be used for .S compiles
124 Asflags []string `android:"arch_variant"`
125
126 // ldflags: list of module-specific flags that will be used for all link steps
127 Ldflags []string `android:"arch_variant"`
128
129 // include_dirs: list of directories relative to the root of the source tree that will
130 // be added to the include path using -I.
131 // If possible, don't use this. If adding paths from the current directory use
132 // local_include_dirs, if adding paths from other modules use export_include_dirs in
133 // that module.
134 Include_dirs []string `android:"arch_variant"`
135
136 // local_include_dirs: list of directories relative to the Blueprints file that will
137 // be added to the include path using -I
138 Local_include_dirs []string `android:"arch_variant"`
139
140 // export_include_dirs: list of directories relative to the Blueprints file that will
141 // be added to the include path using -I for any module that links against this module
142 Export_include_dirs []string
143
144 // clang_cflags: list of module-specific flags that will be used for C and C++ compiles when
145 // compiling with clang
146 Clang_cflags []string `android:"arch_variant"`
147
148 // clang_asflags: list of module-specific flags that will be used for .S compiles when
149 // compiling with clang
150 Clang_asflags []string `android:"arch_variant"`
151
152 // system_shared_libs: list of system libraries that will be dynamically linked to
153 // shared library and executable modules. If unset, generally defaults to libc
154 // and libm. Set to [] to prevent linking against libc and libm.
155 System_shared_libs []string
156
157 // whole_static_libs: list of modules whose object files should be linked into this module
158 // in their entirety. For static library modules, all of the .o files from the intermediate
159 // directory of the dependency will be linked into this modules .a file. For a shared library,
160 // the dependency's .a file will be linked into this module using -Wl,--whole-archive.
161 Whole_static_libs []string `android:"arch_variant"`
162
163 // static_libs: list of modules that should be statically linked into this module.
164 Static_libs []string `android:"arch_variant"`
165
166 // shared_libs: list of modules that should be dynamically linked into this module.
167 Shared_libs []string `android:"arch_variant"`
168
169 // allow_undefined_symbols: allow the module to contain undefined symbols. By default,
170 // modules cannot contain undefined symbols that are not satisified by their immediate
171 // dependencies. Set this flag to true to remove --no-undefined from the linker flags.
172 // This flag should only be necessary for compiling low-level libraries like libc.
173 Allow_undefined_symbols bool
174
175 // nocrt: don't link in crt_begin and crt_end. This flag should only be necessary for
176 // compiling crt or libc.
177 Nocrt bool `android:"arch_variant"`
178
179 // no_default_compiler_flags: don't insert default compiler flags into asflags, cflags,
180 // cppflags, conlyflags, ldflags, or include_dirs
181 No_default_compiler_flags bool
182
183 // clang: compile module with clang instead of gcc
184 Clang bool `android:"arch_variant"`
185
186 // rtti: pass -frtti instead of -fno-rtti
187 Rtti bool
188
189 // host_ldlibs: -l arguments to pass to linker for host-provided shared libraries
190 Host_ldlibs []string `android:"arch_variant"`
191
192 // stl: select the STL library to use. Possible values are "libc++", "libc++_static",
193 // "stlport", "stlport_static", "ndk", "libstdc++", or "none". Leave blank to select the
194 // default
195 Stl string
196
197 // Set for combined shared/static libraries to prevent compiling object files a second time
198 SkipCompileObjs bool `blueprint:"mutated"`
199}
200
201type unusedProperties struct {
202 Asan bool
203 Native_coverage bool
204 Strip string
205 Tags []string
206 Required []string
207}
208
209// Building C/C++ code is handled by objects that satisfy this interface via composition
210type ccModuleType interface {
211 common.AndroidModule
212
213 // Return the cflags that are specific to this _type_ of module
214 moduleTypeCflags(common.AndroidModuleContext, toolchain) []string
215
216 // Return the ldflags that are specific to this _type_ of module
217 moduleTypeLdflags(common.AndroidModuleContext, toolchain) []string
218
219 // Create a ccDeps struct that collects the module dependency info. Can also
220 // modify ccFlags in order to add dependency include directories, etc.
221 collectDeps(common.AndroidModuleContext, ccFlags) (ccDeps, ccFlags)
222
223 // Compile objects into final module
224 compileModule(common.AndroidModuleContext, ccFlags, ccDeps, []string)
225
226 // Return the output file (.o, .a or .so) for use by other modules
227 outputFile() string
228}
229
230func (c *ccBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
231 toolchain := c.findToolchain(ctx)
232 if ctx.Failed() {
233 return
234 }
235
236 flags := c.flags(ctx, toolchain)
237 if ctx.Failed() {
238 return
239 }
240
241 flags = c.addStlFlags(ctx, flags)
242 if ctx.Failed() {
243 return
244 }
245
246 deps, flags := c.ccModuleType().collectDeps(ctx, flags)
247 if ctx.Failed() {
248 return
249 }
250
251 objFiles := c.compileObjs(ctx, flags, deps)
252 if ctx.Failed() {
253 return
254 }
255
256 c.ccModuleType().compileModule(ctx, flags, deps, objFiles)
257 if ctx.Failed() {
258 return
259 }
260}
261
262func (c *ccBase) ccModuleType() ccModuleType {
263 return c.module
264}
265
266var _ common.AndroidDynamicDepender = (*ccBase)(nil)
267
268func (c *ccBase) findToolchain(ctx common.AndroidModuleContext) toolchain {
269 arch := ctx.Arch()
270 factory := toolchainFactories[arch.HostOrDevice][arch.ArchType]
271 if factory == nil {
272 panic(fmt.Sprintf("Toolchain not found for %s arch %q",
273 arch.HostOrDevice.String(), arch.String()))
274 }
275 return factory(arch.ArchVariant, arch.CpuVariant)
276}
277
278type ccDeps struct {
279 staticLibs, sharedLibs, wholeStaticLibs, objFiles, includeDirs []string
280
281 crtBegin, crtEnd string
282}
283
284type ccFlags struct {
285 globalFlags []string
286 asFlags []string
287 cFlags []string
288 conlyFlags []string
289 cppFlags []string
290 ldFlags []string
291 ldLibs []string
292 includeDirs []string
293 nocrt bool
294 toolchain toolchain
295 clang bool
296
297 extraStaticLibs []string
298 extraSharedLibs []string
299}
300
301// ccBase contains the properties and members used by all C/C++ module types
302type ccBase struct {
303 common.AndroidModuleBase
304 module ccModuleType
305
306 properties ccProperties
307 unused unusedProperties
308
309 installPath string
310}
311
312func (c *ccBase) moduleTypeCflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
313 return nil
314}
315
316func (c *ccBase) moduleTypeLdflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
317 return nil
318}
319
320func (c *ccBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
321 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, c.properties.Whole_static_libs...)
322 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, c.properties.Static_libs...)
323 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.properties.Shared_libs...)
324
325 return nil
326}
327
328// Create a ccFlags struct that collects the compile flags from global values,
329// per-target values, module type values, and per-module Blueprints properties
330func (c *ccBase) flags(ctx common.AndroidModuleContext, toolchain toolchain) ccFlags {
331
332 arch := ctx.Arch()
333
334 flags := ccFlags{
335 cFlags: c.properties.Cflags,
336 cppFlags: c.properties.Cppflags,
337 conlyFlags: c.properties.Conlyflags,
338 ldFlags: c.properties.Ldflags,
339 asFlags: c.properties.Asflags,
340 nocrt: c.properties.Nocrt,
341 toolchain: toolchain,
342 clang: c.properties.Clang,
343 }
344
345 if arch.HostOrDevice.Host() {
346 // TODO: allow per-module clang disable for host
347 flags.clang = true
348 }
349
350 if flags.clang {
351 flags.cFlags = clangFilterUnknownCflags(flags.cFlags)
352 flags.cFlags = append(flags.cFlags, c.properties.Clang_cflags...)
353 flags.asFlags = append(flags.asFlags, c.properties.Clang_asflags...)
354 flags.cppFlags = clangFilterUnknownCflags(flags.cppFlags)
355 flags.conlyFlags = clangFilterUnknownCflags(flags.conlyFlags)
356 flags.ldFlags = clangFilterUnknownCflags(flags.ldFlags)
357
358 target := "-target " + toolchain.ClangTriple()
359 gccPrefix := "-B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
360
361 flags.cFlags = append(flags.cFlags, target, gccPrefix)
362 flags.asFlags = append(flags.asFlags, target, gccPrefix)
363 flags.ldFlags = append(flags.ldFlags, target, gccPrefix)
364
365 if arch.HostOrDevice.Host() {
366 gccToolchain := "--gcc-toolchain=" + toolchain.GccRoot()
367 sysroot := "--sysroot=" + filepath.Join(toolchain.GccRoot(), "sysroot")
368
369 // TODO: also need more -B, -L flags to make host builds hermetic
370 flags.cFlags = append(flags.cFlags, gccToolchain, sysroot)
371 flags.asFlags = append(flags.asFlags, gccToolchain, sysroot)
372 flags.ldFlags = append(flags.ldFlags, gccToolchain, sysroot)
373 }
374 }
375
376 flags.includeDirs = pathtools.PrefixPaths(c.properties.Include_dirs, ctx.Config().(Config).SrcDir())
377 localIncludeDirs := pathtools.PrefixPaths(c.properties.Local_include_dirs, common.ModuleSrcDir(ctx))
378 flags.includeDirs = append(flags.includeDirs, localIncludeDirs...)
379
380 if !c.properties.No_default_compiler_flags {
381 flags.includeDirs = append(flags.includeDirs, []string{
382 common.ModuleSrcDir(ctx),
383 common.ModuleOutDir(ctx),
384 common.ModuleGenDir(ctx),
385 }...)
386
387 if arch.HostOrDevice.Device() && !c.properties.Allow_undefined_symbols {
388 flags.ldFlags = append(flags.ldFlags, "-Wl,--no-undefined")
389 }
390
391 if flags.clang {
Tim Kilbournf2948142015-03-11 12:03:03 -0700392 flags.cppFlags = append(flags.cppFlags, "${commonClangGlobalCppflags}")
Colin Cross3f40fa42015-01-30 17:27:36 -0800393 flags.globalFlags = []string{
394 "${commonGlobalIncludes}",
395 toolchain.IncludeFlags(),
396 toolchain.ClangCflags(),
397 "${commonClangGlobalCflags}",
398 fmt.Sprintf("${%sClangGlobalCflags}", arch.HostOrDevice),
399 }
400 } else {
Tim Kilbournf2948142015-03-11 12:03:03 -0700401 flags.cppFlags = append(flags.cppFlags, "${commonGlobalCppflags}")
Colin Cross3f40fa42015-01-30 17:27:36 -0800402 flags.globalFlags = []string{
403 "${commonGlobalIncludes}",
404 toolchain.IncludeFlags(),
405 toolchain.Cflags(),
406 "${commonGlobalCflags}",
407 fmt.Sprintf("${%sGlobalCflags}", arch.HostOrDevice),
408 }
409 }
410
411 if arch.HostOrDevice.Host() {
412 flags.ldFlags = append(flags.ldFlags, c.properties.Host_ldlibs...)
413 }
414
415 if arch.HostOrDevice.Device() {
416 if c.properties.Rtti {
417 flags.cppFlags = append(flags.cppFlags, "-frtti")
418 } else {
419 flags.cppFlags = append(flags.cppFlags, "-fno-rtti")
420 }
421 }
422
423 flags.asFlags = append(flags.asFlags, "-D__ASSEMBLY__")
424
425 if flags.clang {
426 flags.cppFlags = append(flags.cppFlags, toolchain.ClangCppflags())
427 flags.ldFlags = append(flags.ldFlags, toolchain.ClangLdflags())
428 } else {
429 flags.cppFlags = append(flags.cppFlags, toolchain.Cppflags())
430 flags.ldFlags = append(flags.ldFlags, toolchain.Ldflags())
431 }
432 }
433
434 flags.cFlags = append(flags.cFlags, c.ccModuleType().moduleTypeCflags(ctx, toolchain)...)
435 flags.ldFlags = append(flags.ldFlags, c.ccModuleType().moduleTypeLdflags(ctx, toolchain)...)
436
437 // Optimization to reduce size of build.ninja
438 // Replace the long list of flags for each file with a module-local variable
439 ctx.Variable(pctx, "cflags", strings.Join(flags.cFlags, " "))
440 ctx.Variable(pctx, "cppflags", strings.Join(flags.cppFlags, " "))
441 ctx.Variable(pctx, "asflags", strings.Join(flags.asFlags, " "))
442 flags.cFlags = []string{"$cflags"}
443 flags.cppFlags = []string{"$cppflags"}
444 flags.asFlags = []string{"$asflags"}
445
446 return flags
447}
448
449// Modify ccFlags structs with STL library info
450func (c *ccBase) addStlFlags(ctx common.AndroidModuleContext, flags ccFlags) ccFlags {
451 if !c.properties.No_default_compiler_flags {
452 arch := ctx.Arch()
453 stl := "libc++" // TODO: mingw needs libstdc++
454 if c.properties.Stl != "" {
455 stl = c.properties.Stl
456 }
457
458 stlStatic := false
459 if strings.HasSuffix(stl, "_static") {
460 stlStatic = true
461 }
462
463 switch stl {
464 case "libc++", "libc++_static":
465 flags.cFlags = append(flags.cFlags, "-D_USING_LIBCXX")
466 flags.includeDirs = append(flags.includeDirs, "${SrcDir}/external/libcxx/include")
467 if arch.HostOrDevice.Host() {
468 flags.cppFlags = append(flags.cppFlags, "-nostdinc++")
469 flags.ldFlags = append(flags.ldFlags, "-nodefaultlibs")
470 flags.ldLibs = append(flags.ldLibs, "-lc", "-lm", "-lpthread")
471 }
472 if stlStatic {
473 flags.extraStaticLibs = append(flags.extraStaticLibs, "libc++_static")
474 } else {
475 flags.extraSharedLibs = append(flags.extraSharedLibs, "libc++")
476 }
477 case "stlport", "stlport_static":
478 if arch.HostOrDevice.Device() {
479 flags.includeDirs = append(flags.includeDirs,
480 "${SrcDir}/external/stlport/stlport",
481 "${SrcDir}/bionic/libstdc++/include",
482 "${SrcDir}/bionic")
483 if stlStatic {
484 flags.extraStaticLibs = append(flags.extraStaticLibs, "libstdc++", "libstlport_static")
485 } else {
486 flags.extraSharedLibs = append(flags.extraSharedLibs, "libstdc++", "libstlport")
487 }
488 }
489 case "ndk":
490 panic("TODO")
491 case "libstdc++":
492 // Using bionic's basic libstdc++. Not actually an STL. Only around until the
493 // tree is in good enough shape to not need it.
494 // Host builds will use GNU libstdc++.
495 if arch.HostOrDevice.Device() {
496 flags.includeDirs = append(flags.includeDirs, "${SrcDir}/bionic/libstdc++/include")
497 flags.extraSharedLibs = append(flags.extraSharedLibs, "libstdc++")
498 }
499 case "none":
500 if arch.HostOrDevice.Host() {
501 flags.cppFlags = append(flags.cppFlags, "-nostdinc++")
502 flags.ldFlags = append(flags.ldFlags, "-nodefaultlibs")
503 flags.ldLibs = append(flags.ldLibs, "-lc", "-lm")
504 }
505 default:
506 ctx.ModuleErrorf("stl: %q is not a supported STL", stl)
507 }
508
509 }
510 return flags
511}
512
513// Compile a list of source files into objects a specified subdirectory
514func (c *ccBase) customCompileObjs(ctx common.AndroidModuleContext, flags ccFlags,
515 deps ccDeps, subdir string, srcFiles []string) []string {
516
517 srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx))
518 srcFiles = common.ExpandGlobs(ctx, srcFiles)
519
520 return TransformSourceToObj(ctx, subdir, srcFiles, ccFlagsToBuilderFlags(flags))
521}
522
523// Compile files listed in c.properties.Srcs into objects
524func (c *ccBase) compileObjs(ctx common.AndroidModuleContext, flags ccFlags,
525 deps ccDeps) []string {
526
527 if c.properties.SkipCompileObjs {
528 return nil
529 }
530
531 return c.customCompileObjs(ctx, flags, deps, "", c.properties.Srcs)
532}
533
534func (c *ccBase) outputFile() string {
535 return ""
536}
537
538func (c *ccBase) collectDepsFromList(ctx common.AndroidModuleContext,
539 names []string) (modules []common.AndroidModule,
540 outputFiles []string, exportedIncludeDirs []string) {
541
542 for _, n := range names {
543 found := false
544 ctx.VisitDirectDeps(func(m blueprint.Module) {
545 otherName := ctx.OtherModuleName(m)
546 if otherName != n {
547 return
548 }
549
550 if a, ok := m.(ccModuleType); ok {
551 if a.Disabled() {
552 // If a cc_library host+device module depends on a library that exists as both
553 // cc_library_shared and cc_library_host_shared, it will end up with two
554 // dependencies with the same name, one of which is marked disabled for each
555 // of host and device. Ignore the disabled one.
556 return
557 }
558 if a.HostOrDevice() != ctx.Arch().HostOrDevice {
559 ctx.ModuleErrorf("host/device mismatch between %q and %q", ctx.ModuleName(),
560 otherName)
561 return
562 }
563
564 if outputFile := a.outputFile(); outputFile != "" {
565 if found {
566 ctx.ModuleErrorf("multiple modules satisified dependency on %q", otherName)
567 return
568 }
569 outputFiles = append(outputFiles, outputFile)
570 modules = append(modules, a)
571 if i, ok := a.(ccExportedIncludeDirsProducer); ok {
572 exportedIncludeDirs = append(exportedIncludeDirs, i.exportedIncludeDirs()...)
573 }
574 found = true
575 } else {
576 ctx.ModuleErrorf("module %q missing output file", otherName)
577 return
578 }
579 } else {
580 ctx.ModuleErrorf("module %q not an android module", otherName)
581 return
582 }
583 })
584 if !found {
585 ctx.ModuleErrorf("unsatisified dependency on %q", n)
586 }
587 }
588
589 return modules, outputFiles, exportedIncludeDirs
590}
591
592func (c *ccBase) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
593 var deps ccDeps
594 var newIncludeDirs []string
595
596 wholeStaticLibNames := c.properties.Whole_static_libs
597 _, deps.wholeStaticLibs, newIncludeDirs = c.collectDepsFromList(ctx, wholeStaticLibNames)
598
599 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
600
601 staticLibNames := c.properties.Static_libs
602 staticLibNames = append(staticLibNames, flags.extraStaticLibs...)
603 _, deps.staticLibs, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
604 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
605
606 return deps, flags
607}
608
609// ccDynamic contains the properties and members used by shared libraries and dynamic executables
610type ccDynamic struct {
611 ccBase
612}
613
614const defaultSystemSharedLibraries = "__default__"
615
616func (c *ccDynamic) systemSharedLibs() []string {
617
618 if len(c.properties.System_shared_libs) == 1 &&
619 c.properties.System_shared_libs[0] == defaultSystemSharedLibraries {
620
621 if c.HostOrDevice().Host() {
622 return []string{}
623 } else {
624 return []string{"libc", "libm"}
625 }
626 }
627 return c.properties.System_shared_libs
628}
629
630var (
631 stlSharedLibs = []string{"libc++", "libstlport", "libstdc++"}
632 stlSharedHostLibs = []string{"libc++"}
633 stlStaticLibs = []string{"libc++_static", "libstlport_static", "libstdc++"}
634 stlStaticHostLibs = []string{"libc++_static"}
635)
636
637func (c *ccDynamic) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
638 deps := c.ccBase.AndroidDynamicDependencies(ctx)
639
640 if c.HostOrDevice().Device() {
641 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.systemSharedLibs()...)
642 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}},
643 "libcompiler_rt-extras",
644 //"libgcov",
645 "libatomic",
646 "libgcc")
647
648 if c.properties.Stl != "none" {
649 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, stlSharedLibs...)
650 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, stlStaticLibs...)
651 }
652 } else {
653 if c.properties.Stl != "none" {
654 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, stlSharedHostLibs...)
655 ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, stlStaticHostLibs...)
656 }
657 }
658
659 return deps
660}
661
662var implicitStaticLibs = []string{"libcompiler_rt-extras" /*"libgcov",*/, "libatomic", "libgcc"}
663
664func (c *ccDynamic) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
665 var newIncludeDirs []string
666
667 deps, flags := c.ccBase.collectDeps(ctx, flags)
668
669 systemSharedLibs := c.systemSharedLibs()
670 sharedLibNames := make([]string, 0, len(c.properties.Shared_libs)+len(systemSharedLibs)+
671 len(flags.extraSharedLibs))
672 sharedLibNames = append(sharedLibNames, c.properties.Shared_libs...)
673 sharedLibNames = append(sharedLibNames, systemSharedLibs...)
674 sharedLibNames = append(sharedLibNames, flags.extraSharedLibs...)
675 _, deps.sharedLibs, newIncludeDirs = c.collectDepsFromList(ctx, sharedLibNames)
676 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
677
678 if ctx.Arch().HostOrDevice.Device() {
679 var staticLibs []string
680 staticLibNames := implicitStaticLibs
681 _, staticLibs, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
682 deps.staticLibs = append(deps.staticLibs, staticLibs...)
683 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
684 }
685
686 ctx.VisitDirectDeps(func(m blueprint.Module) {
687 if obj, ok := m.(*ccObject); ok {
688 otherName := ctx.OtherModuleName(m)
689 if strings.HasPrefix(otherName, "crtbegin") {
690 if !c.properties.Nocrt {
691 deps.crtBegin = obj.outputFile()
692 }
693 } else if strings.HasPrefix(otherName, "crtend") {
694 if !c.properties.Nocrt {
695 deps.crtEnd = obj.outputFile()
696 }
697 } else {
698 ctx.ModuleErrorf("object module type only support for crtbegin and crtend, found %q",
699 ctx.OtherModuleName(m))
700 }
701 }
702 })
703
704 flags.includeDirs = append(flags.includeDirs, deps.includeDirs...)
705
706 return deps, flags
707}
708
709type ccExportedIncludeDirsProducer interface {
710 exportedIncludeDirs() []string
711}
712
713//
714// Combined static+shared libraries
715//
716
717type ccLibrary struct {
718 ccDynamic
719
720 primary *ccLibrary
721 primaryObjFiles []string
722 objFiles []string
723 exportIncludeDirs []string
724 out string
725
726 libraryProperties struct {
727 BuildStatic bool `blueprint:"mutated"`
728 BuildShared bool `blueprint:"mutated"`
729 IsShared bool `blueprint:"mutated"`
730 IsStatic bool `blueprint:"mutated"`
731
732 Static struct {
733 Srcs []string `android:"arch_variant"`
734 Cflags []string `android:"arch_variant"`
735 } `android:"arch_variant"`
736 Shared struct {
737 Srcs []string `android:"arch_variant"`
738 Cflags []string `android:"arch_variant"`
739 } `android:"arch_variant"`
740 }
741}
742
743func NewCCLibrary() (blueprint.Module, []interface{}) {
744 module := &ccLibrary{}
745 module.module = module
746 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
747 module.libraryProperties.BuildShared = true
748 module.libraryProperties.BuildStatic = true
749
750 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
751 &module.properties, &module.unused, &module.libraryProperties)
752}
753
754func (c *ccLibrary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
755 if c.libraryProperties.IsShared {
756 deps := c.ccDynamic.AndroidDynamicDependencies(ctx)
757 if c.HostOrDevice().Device() {
758 deps = append(deps, "crtbegin_so", "crtend_so")
759 }
760 return deps
761 } else {
762 return c.ccBase.AndroidDynamicDependencies(ctx)
763 }
764}
765
766func (c *ccLibrary) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
767 if c.libraryProperties.IsStatic {
768 deps, flags := c.ccBase.collectDeps(ctx, flags)
769 wholeStaticLibNames := c.properties.Whole_static_libs
770 wholeStaticLibs, _, _ := c.collectDepsFromList(ctx, wholeStaticLibNames)
771
772 for _, m := range wholeStaticLibs {
773 if staticLib, ok := m.(*ccLibrary); ok && staticLib.libraryProperties.IsStatic {
774 deps.objFiles = append(deps.objFiles, staticLib.allObjFiles()...)
775 } else {
776 ctx.ModuleErrorf("module %q not a static library", ctx.OtherModuleName(m))
777 }
778 }
779
780 return deps, flags
781 } else if c.libraryProperties.IsShared {
782 return c.ccDynamic.collectDeps(ctx, flags)
783 } else {
784 panic("Not shared or static")
785 }
786}
787
788func (c *ccLibrary) outputFile() string {
789 return c.out
790}
791
792func (c *ccLibrary) allObjFiles() []string {
793 return c.objFiles
794}
795
796func (c *ccLibrary) exportedIncludeDirs() []string {
797 return c.exportIncludeDirs
798}
799
800func (c *ccLibrary) moduleTypeCflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
801 return []string{"-fPIC"}
802}
803
804func (c *ccLibrary) moduleTypeLdflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
805 if c.libraryProperties.IsShared {
806 libName := ctx.ModuleName()
807 // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
808 sharedFlag := "-Wl,-shared"
809 if c.properties.Clang || ctx.Arch().HostOrDevice.Host() {
810 sharedFlag = "-shared"
811 }
812 if ctx.Arch().HostOrDevice.Device() {
813 return []string{
814 "-nostdlib",
815 "-Wl,--gc-sections",
816 sharedFlag,
817 "-Wl,-soname," + libName,
818 }
819 } else {
820 return []string{
821 "-Wl,--gc-sections",
822 sharedFlag,
823 "-Wl,-soname," + libName,
824 }
825 }
826 } else {
827 return nil
828 }
829}
830
831func (c *ccLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
832 flags ccFlags, deps ccDeps, objFiles []string) {
833
834 staticFlags := flags
835 staticFlags.cFlags = append(staticFlags.cFlags, c.libraryProperties.Static.Cflags...)
836 objFilesStatic := c.customCompileObjs(ctx, staticFlags, deps, common.DeviceStaticLibrary,
837 c.libraryProperties.Static.Srcs)
838
839 objFiles = append(objFiles, objFilesStatic...)
840
841 var includeDirs []string
842
843 wholeStaticLibNames := c.properties.Whole_static_libs
844 wholeStaticLibs, _, newIncludeDirs := c.collectDepsFromList(ctx, wholeStaticLibNames)
845 includeDirs = append(includeDirs, newIncludeDirs...)
846
847 for _, m := range wholeStaticLibs {
848 if staticLib, ok := m.(*ccLibrary); ok && staticLib.libraryProperties.IsStatic {
849 objFiles = append(objFiles, staticLib.allObjFiles()...)
850 } else {
851 ctx.ModuleErrorf("module %q not a static library", ctx.OtherModuleName(m))
852 }
853 }
854
855 staticLibNames := c.properties.Static_libs
856 _, _, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
857 includeDirs = append(includeDirs, newIncludeDirs...)
858
859 ctx.VisitDirectDeps(func(m blueprint.Module) {
860 if obj, ok := m.(*ccObject); ok {
861 otherName := ctx.OtherModuleName(m)
862 if !strings.HasPrefix(otherName, "crtbegin") && !strings.HasPrefix(otherName, "crtend") {
863 objFiles = append(objFiles, obj.outputFile())
864 }
865 }
866 })
867
868 outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+staticLibraryExtension)
869
870 TransformObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
871
872 c.objFiles = objFiles
873 c.out = outputFile
874 c.exportIncludeDirs = pathtools.PrefixPaths(c.properties.Export_include_dirs,
875 common.ModuleSrcDir(ctx))
876
877 ctx.CheckbuildFile(outputFile)
878}
879
880func (c *ccLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
881 flags ccFlags, deps ccDeps, objFiles []string) {
882
883 sharedFlags := flags
884 sharedFlags.cFlags = append(sharedFlags.cFlags, c.libraryProperties.Shared.Cflags...)
885 objFilesShared := c.customCompileObjs(ctx, sharedFlags, deps, common.DeviceSharedLibrary,
886 c.libraryProperties.Shared.Srcs)
887
888 objFiles = append(objFiles, objFilesShared...)
889
890 outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+sharedLibraryExtension)
891
892 TransformObjToDynamicBinary(ctx, objFiles, deps.sharedLibs, deps.staticLibs, deps.wholeStaticLibs,
893 deps.crtBegin, deps.crtEnd, ccFlagsToBuilderFlags(flags), outputFile)
894
895 c.out = outputFile
896 c.exportIncludeDirs = pathtools.PrefixPaths(c.properties.Export_include_dirs,
897 common.ModuleSrcDir(ctx))
898
899 installDir := "lib"
900 if flags.toolchain.Is64Bit() {
901 installDir = "lib64"
902 }
903
904 ctx.InstallFile(installDir, outputFile)
905}
906
907func (c *ccLibrary) compileModule(ctx common.AndroidModuleContext,
908 flags ccFlags, deps ccDeps, objFiles []string) {
909
910 // Reuse the object files from the matching static library if it exists
911 if c.primary == c {
912 c.primaryObjFiles = objFiles
913 } else {
914 objFiles = append([]string(nil), c.primary.primaryObjFiles...)
915 }
916
917 if c.libraryProperties.IsStatic {
918 c.compileStaticLibrary(ctx, flags, deps, objFiles)
919 } else {
920 c.compileSharedLibrary(ctx, flags, deps, objFiles)
921 }
922}
923
924//
925// Objects (for crt*.o)
926//
927
928type ccObject struct {
929 ccBase
930 out string
931}
932
933func NewCCObject() (blueprint.Module, []interface{}) {
934 module := &ccObject{}
935 module.module = module
936
937 return common.InitAndroidModule(module, common.DeviceSupported, "both",
938 &module.properties, &module.unused)
939}
940
941func (*ccObject) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
942 // object files can't have any dynamic dependencies
943 return nil
944}
945
946func (c *ccObject) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
947 deps, flags := c.ccBase.collectDeps(ctx, flags)
948 ctx.VisitDirectDeps(func(m blueprint.Module) {
949 if obj, ok := m.(*ccObject); ok {
950 deps.objFiles = append(deps.objFiles, obj.outputFile())
951 } else {
952 ctx.ModuleErrorf("Unknown module type for dependency %q", ctx.OtherModuleName(m))
953 }
954 })
955
956 return deps, flags
957}
958
959func (c *ccObject) compileModule(ctx common.AndroidModuleContext,
960 flags ccFlags, deps ccDeps, objFiles []string) {
961
962 objFiles = append(objFiles, deps.objFiles...)
963
964 var outputFile string
965 if len(objFiles) == 1 {
966 outputFile = objFiles[0]
967 } else {
968 outputFile = filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+".o")
969 TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
970 }
971
972 c.out = outputFile
973
974 ctx.CheckbuildFile(outputFile)
975}
976
977func (c *ccObject) outputFile() string {
978 return c.out
979}
980
981//
982// Executables
983//
984
985type ccBinary struct {
986 ccDynamic
987 binaryProperties binaryProperties
988}
989
990type binaryProperties struct {
991 // static_executable: compile executable with -static
992 Static_executable bool
993
994 // stem: set the name of the output
995 Stem string `android:"arch_variant"`
996
997 // prefix_symbols: if set, add an extra objcopy --prefix-symbols= step
998 Prefix_symbols string
999}
1000
1001func (c *ccBinary) getStem(ctx common.AndroidModuleContext) string {
1002 if c.binaryProperties.Stem != "" {
1003 return c.binaryProperties.Stem
1004 }
1005 return ctx.ModuleName()
1006}
1007
1008func (c *ccBinary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
1009 deps := c.ccDynamic.AndroidDynamicDependencies(ctx)
1010 if c.HostOrDevice().Device() {
1011 if c.binaryProperties.Static_executable {
1012 deps = append(deps, "crtbegin_static", "crtend_android")
1013 } else {
1014 deps = append(deps, "crtbegin_dynamic", "crtend_android")
1015 }
1016 }
1017 return deps
1018}
1019
1020func NewCCBinary() (blueprint.Module, []interface{}) {
1021 module := &ccBinary{}
1022 module.module = module
1023
1024 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
1025 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "first", &module.properties,
1026 &module.unused, &module.binaryProperties)
1027}
1028
1029func (c *ccBinary) moduleTypeCflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
1030 return []string{"-fpie"}
1031}
1032
1033func (c *ccBinary) moduleTypeLdflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
1034 if ctx.Arch().HostOrDevice.Device() {
1035 linker := "/system/bin/linker"
1036 if toolchain.Is64Bit() {
1037 linker = "/system/bin/linker64"
1038 }
1039
1040 return []string{
1041 "-nostdlib",
1042 "-Bdynamic",
1043 fmt.Sprintf("-Wl,-dynamic-linker,%s", linker),
1044 "-Wl,--gc-sections",
1045 "-Wl,-z,nocopyreloc",
1046 }
1047 }
1048
1049 return nil
1050}
1051
1052func (c *ccBinary) compileModule(ctx common.AndroidModuleContext,
1053 flags ccFlags, deps ccDeps, objFiles []string) {
1054
1055 if !c.binaryProperties.Static_executable && inList("libc", c.properties.Static_libs) {
1056 ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
1057 "from static libs or set static_executable: true")
1058 }
1059
1060 outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx))
1061
1062 TransformObjToDynamicBinary(ctx, objFiles, deps.sharedLibs, deps.staticLibs, deps.wholeStaticLibs,
1063 deps.crtBegin, deps.crtEnd, ccFlagsToBuilderFlags(flags), outputFile)
1064
1065 ctx.InstallFile("bin", outputFile)
1066}
1067
1068//
1069// Static library
1070//
1071
1072func NewCCLibraryStatic() (blueprint.Module, []interface{}) {
1073 module := &ccLibrary{}
1074 module.module = module
1075 module.libraryProperties.BuildStatic = true
1076
1077 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
1078 &module.properties, &module.unused)
1079}
1080
1081//
1082// Shared libraries
1083//
1084
1085func NewCCLibraryShared() (blueprint.Module, []interface{}) {
1086 module := &ccLibrary{}
1087 module.module = module
1088 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
1089 module.libraryProperties.BuildShared = true
1090
1091 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
1092 &module.properties, &module.unused)
1093}
1094
1095//
1096// Host static library
1097//
1098
1099func NewCCLibraryHostStatic() (blueprint.Module, []interface{}) {
1100 module := &ccLibrary{}
1101 module.module = module
1102 module.libraryProperties.BuildStatic = true
1103
1104 return common.InitAndroidModule(module, common.HostSupported, "both",
1105 &module.properties, &module.unused)
1106}
1107
1108//
1109// Host Shared libraries
1110//
1111
1112func NewCCLibraryHostShared() (blueprint.Module, []interface{}) {
1113 module := &ccLibrary{}
1114 module.module = module
1115 module.libraryProperties.BuildShared = true
1116
1117 return common.InitAndroidModule(module, common.HostSupported, "both",
1118 &module.properties, &module.unused)
1119}
1120
1121//
1122// Host Binaries
1123//
1124
1125func NewCCBinaryHost() (blueprint.Module, []interface{}) {
1126 module := &ccBinary{}
1127 module.module = module
1128
1129 return common.InitAndroidModule(module, common.HostSupported, "first",
1130 &module.properties, &module.unused)
1131}
1132
1133//
1134// Device libraries shipped with gcc
1135//
1136
1137type toolchainLibrary struct {
1138 ccLibrary
1139}
1140
1141func (*toolchainLibrary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
1142 // toolchain libraries can't have any dependencies
1143 return nil
1144}
1145
1146func (*toolchainLibrary) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
1147 // toolchain libraries can't have any dependencies
1148 return ccDeps{}, flags
1149}
1150
1151func NewToolchainLibrary() (blueprint.Module, []interface{}) {
1152 module := &toolchainLibrary{}
1153 module.module = module
1154 module.libraryProperties.BuildStatic = true
1155
1156 return common.InitAndroidModule(module, common.DeviceSupported, "both")
1157}
1158
1159func (c *toolchainLibrary) compileModule(ctx common.AndroidModuleContext,
1160 flags ccFlags, deps ccDeps, objFiles []string) {
1161
1162 libName := ctx.ModuleName() + staticLibraryExtension
1163 outputFile := filepath.Join(common.ModuleOutDir(ctx), libName)
1164
1165 CopyGccLib(ctx, libName, ccFlagsToBuilderFlags(flags), outputFile)
1166
1167 c.out = outputFile
1168
1169 ctx.CheckbuildFile(outputFile)
1170}
1171
1172func LinkageMutator(mctx blueprint.EarlyMutatorContext) {
1173 if c, ok := mctx.Module().(*ccLibrary); ok {
1174 var modules []blueprint.Module
1175 if c.libraryProperties.BuildStatic && c.libraryProperties.BuildShared {
1176 modules = mctx.CreateLocalVariations("static", "shared")
1177 modules[0].(*ccLibrary).libraryProperties.IsStatic = true
1178 modules[1].(*ccLibrary).libraryProperties.IsShared = true
1179 } else if c.libraryProperties.BuildStatic {
1180 modules = mctx.CreateLocalVariations("static")
1181 modules[0].(*ccLibrary).libraryProperties.IsStatic = true
1182 } else if c.libraryProperties.BuildShared {
1183 modules = mctx.CreateLocalVariations("shared")
1184 modules[0].(*ccLibrary).libraryProperties.IsShared = true
1185 } else {
1186 panic("ccLibrary not static or shared")
1187 }
1188 primary := modules[0].(*ccLibrary)
1189 for _, m := range modules {
1190 m.(*ccLibrary).primary = primary
1191 if m != primary {
1192 m.(*ccLibrary).properties.SkipCompileObjs = true
1193 }
1194 }
1195 } else if _, ok := mctx.Module().(*toolchainLibrary); ok {
1196 mctx.CreateLocalVariations("static")
1197 }
1198}