blob: 98c328f86abe5daff1964fe30f58fda2dc1e509b [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 {
Colin Cross77b00fa2015-03-16 16:15:49 -0700279 staticLibs, sharedLibs, lateStaticLibs, wholeStaticLibs, objFiles, includeDirs []string
Colin Cross3f40fa42015-01-30 17:27:36 -0800280
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",
Colin Cross77b00fa2015-03-16 16:15:49 -0700644 "libgcov",
Colin Cross3f40fa42015-01-30 17:27:36 -0800645 "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
Colin Cross3f40fa42015-01-30 17:27:36 -0800662func (c *ccDynamic) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
663 var newIncludeDirs []string
664
665 deps, flags := c.ccBase.collectDeps(ctx, flags)
666
667 systemSharedLibs := c.systemSharedLibs()
668 sharedLibNames := make([]string, 0, len(c.properties.Shared_libs)+len(systemSharedLibs)+
669 len(flags.extraSharedLibs))
670 sharedLibNames = append(sharedLibNames, c.properties.Shared_libs...)
671 sharedLibNames = append(sharedLibNames, systemSharedLibs...)
672 sharedLibNames = append(sharedLibNames, flags.extraSharedLibs...)
673 _, deps.sharedLibs, newIncludeDirs = c.collectDepsFromList(ctx, sharedLibNames)
674 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
675
676 if ctx.Arch().HostOrDevice.Device() {
677 var staticLibs []string
Colin Cross77b00fa2015-03-16 16:15:49 -0700678 staticLibNames := []string{"libcompiler_rt-extras"}
Colin Cross3f40fa42015-01-30 17:27:36 -0800679 _, staticLibs, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
680 deps.staticLibs = append(deps.staticLibs, staticLibs...)
681 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
Colin Cross77b00fa2015-03-16 16:15:49 -0700682
683 // libgcc and libatomic have to be last on the command line
684 staticLibNames = []string{"libgcov", "libatomic", "libgcc"}
685 _, staticLibs, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
686 deps.lateStaticLibs = append(deps.lateStaticLibs, staticLibs...)
687 deps.includeDirs = append(deps.includeDirs, newIncludeDirs...)
Colin Cross3f40fa42015-01-30 17:27:36 -0800688 }
689
690 ctx.VisitDirectDeps(func(m blueprint.Module) {
691 if obj, ok := m.(*ccObject); ok {
692 otherName := ctx.OtherModuleName(m)
693 if strings.HasPrefix(otherName, "crtbegin") {
694 if !c.properties.Nocrt {
695 deps.crtBegin = obj.outputFile()
696 }
697 } else if strings.HasPrefix(otherName, "crtend") {
698 if !c.properties.Nocrt {
699 deps.crtEnd = obj.outputFile()
700 }
701 } else {
702 ctx.ModuleErrorf("object module type only support for crtbegin and crtend, found %q",
703 ctx.OtherModuleName(m))
704 }
705 }
706 })
707
708 flags.includeDirs = append(flags.includeDirs, deps.includeDirs...)
709
710 return deps, flags
711}
712
713type ccExportedIncludeDirsProducer interface {
714 exportedIncludeDirs() []string
715}
716
717//
718// Combined static+shared libraries
719//
720
721type ccLibrary struct {
722 ccDynamic
723
724 primary *ccLibrary
725 primaryObjFiles []string
726 objFiles []string
727 exportIncludeDirs []string
728 out string
729
730 libraryProperties struct {
731 BuildStatic bool `blueprint:"mutated"`
732 BuildShared bool `blueprint:"mutated"`
733 IsShared bool `blueprint:"mutated"`
734 IsStatic bool `blueprint:"mutated"`
735
736 Static struct {
737 Srcs []string `android:"arch_variant"`
738 Cflags []string `android:"arch_variant"`
739 } `android:"arch_variant"`
740 Shared struct {
741 Srcs []string `android:"arch_variant"`
742 Cflags []string `android:"arch_variant"`
743 } `android:"arch_variant"`
744 }
745}
746
747func NewCCLibrary() (blueprint.Module, []interface{}) {
748 module := &ccLibrary{}
749 module.module = module
750 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
751 module.libraryProperties.BuildShared = true
752 module.libraryProperties.BuildStatic = true
753
754 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
755 &module.properties, &module.unused, &module.libraryProperties)
756}
757
758func (c *ccLibrary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
759 if c.libraryProperties.IsShared {
760 deps := c.ccDynamic.AndroidDynamicDependencies(ctx)
761 if c.HostOrDevice().Device() {
762 deps = append(deps, "crtbegin_so", "crtend_so")
763 }
764 return deps
765 } else {
766 return c.ccBase.AndroidDynamicDependencies(ctx)
767 }
768}
769
770func (c *ccLibrary) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
771 if c.libraryProperties.IsStatic {
772 deps, flags := c.ccBase.collectDeps(ctx, flags)
773 wholeStaticLibNames := c.properties.Whole_static_libs
774 wholeStaticLibs, _, _ := c.collectDepsFromList(ctx, wholeStaticLibNames)
775
776 for _, m := range wholeStaticLibs {
777 if staticLib, ok := m.(*ccLibrary); ok && staticLib.libraryProperties.IsStatic {
778 deps.objFiles = append(deps.objFiles, staticLib.allObjFiles()...)
779 } else {
780 ctx.ModuleErrorf("module %q not a static library", ctx.OtherModuleName(m))
781 }
782 }
783
784 return deps, flags
785 } else if c.libraryProperties.IsShared {
786 return c.ccDynamic.collectDeps(ctx, flags)
787 } else {
788 panic("Not shared or static")
789 }
790}
791
792func (c *ccLibrary) outputFile() string {
793 return c.out
794}
795
796func (c *ccLibrary) allObjFiles() []string {
797 return c.objFiles
798}
799
800func (c *ccLibrary) exportedIncludeDirs() []string {
801 return c.exportIncludeDirs
802}
803
804func (c *ccLibrary) moduleTypeCflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
805 return []string{"-fPIC"}
806}
807
808func (c *ccLibrary) moduleTypeLdflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
809 if c.libraryProperties.IsShared {
810 libName := ctx.ModuleName()
811 // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
812 sharedFlag := "-Wl,-shared"
813 if c.properties.Clang || ctx.Arch().HostOrDevice.Host() {
814 sharedFlag = "-shared"
815 }
816 if ctx.Arch().HostOrDevice.Device() {
817 return []string{
818 "-nostdlib",
819 "-Wl,--gc-sections",
820 sharedFlag,
821 "-Wl,-soname," + libName,
822 }
823 } else {
824 return []string{
825 "-Wl,--gc-sections",
826 sharedFlag,
827 "-Wl,-soname," + libName,
828 }
829 }
830 } else {
831 return nil
832 }
833}
834
835func (c *ccLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
836 flags ccFlags, deps ccDeps, objFiles []string) {
837
838 staticFlags := flags
839 staticFlags.cFlags = append(staticFlags.cFlags, c.libraryProperties.Static.Cflags...)
840 objFilesStatic := c.customCompileObjs(ctx, staticFlags, deps, common.DeviceStaticLibrary,
841 c.libraryProperties.Static.Srcs)
842
843 objFiles = append(objFiles, objFilesStatic...)
844
845 var includeDirs []string
846
847 wholeStaticLibNames := c.properties.Whole_static_libs
848 wholeStaticLibs, _, newIncludeDirs := c.collectDepsFromList(ctx, wholeStaticLibNames)
849 includeDirs = append(includeDirs, newIncludeDirs...)
850
851 for _, m := range wholeStaticLibs {
852 if staticLib, ok := m.(*ccLibrary); ok && staticLib.libraryProperties.IsStatic {
853 objFiles = append(objFiles, staticLib.allObjFiles()...)
854 } else {
855 ctx.ModuleErrorf("module %q not a static library", ctx.OtherModuleName(m))
856 }
857 }
858
859 staticLibNames := c.properties.Static_libs
860 _, _, newIncludeDirs = c.collectDepsFromList(ctx, staticLibNames)
861 includeDirs = append(includeDirs, newIncludeDirs...)
862
863 ctx.VisitDirectDeps(func(m blueprint.Module) {
864 if obj, ok := m.(*ccObject); ok {
865 otherName := ctx.OtherModuleName(m)
866 if !strings.HasPrefix(otherName, "crtbegin") && !strings.HasPrefix(otherName, "crtend") {
867 objFiles = append(objFiles, obj.outputFile())
868 }
869 }
870 })
871
872 outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+staticLibraryExtension)
873
874 TransformObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
875
876 c.objFiles = objFiles
877 c.out = outputFile
878 c.exportIncludeDirs = pathtools.PrefixPaths(c.properties.Export_include_dirs,
879 common.ModuleSrcDir(ctx))
880
881 ctx.CheckbuildFile(outputFile)
882}
883
884func (c *ccLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
885 flags ccFlags, deps ccDeps, objFiles []string) {
886
887 sharedFlags := flags
888 sharedFlags.cFlags = append(sharedFlags.cFlags, c.libraryProperties.Shared.Cflags...)
889 objFilesShared := c.customCompileObjs(ctx, sharedFlags, deps, common.DeviceSharedLibrary,
890 c.libraryProperties.Shared.Srcs)
891
892 objFiles = append(objFiles, objFilesShared...)
893
894 outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+sharedLibraryExtension)
895
Colin Cross77b00fa2015-03-16 16:15:49 -0700896 TransformObjToDynamicBinary(ctx, objFiles, deps.sharedLibs, deps.staticLibs,
897 deps.lateStaticLibs, deps.wholeStaticLibs, deps.crtBegin, deps.crtEnd,
898 ccFlagsToBuilderFlags(flags), outputFile)
Colin Cross3f40fa42015-01-30 17:27:36 -0800899
900 c.out = outputFile
901 c.exportIncludeDirs = pathtools.PrefixPaths(c.properties.Export_include_dirs,
902 common.ModuleSrcDir(ctx))
903
904 installDir := "lib"
905 if flags.toolchain.Is64Bit() {
906 installDir = "lib64"
907 }
908
909 ctx.InstallFile(installDir, outputFile)
910}
911
912func (c *ccLibrary) compileModule(ctx common.AndroidModuleContext,
913 flags ccFlags, deps ccDeps, objFiles []string) {
914
915 // Reuse the object files from the matching static library if it exists
916 if c.primary == c {
917 c.primaryObjFiles = objFiles
918 } else {
919 objFiles = append([]string(nil), c.primary.primaryObjFiles...)
920 }
921
922 if c.libraryProperties.IsStatic {
923 c.compileStaticLibrary(ctx, flags, deps, objFiles)
924 } else {
925 c.compileSharedLibrary(ctx, flags, deps, objFiles)
926 }
927}
928
929//
930// Objects (for crt*.o)
931//
932
933type ccObject struct {
934 ccBase
935 out string
936}
937
938func NewCCObject() (blueprint.Module, []interface{}) {
939 module := &ccObject{}
940 module.module = module
941
942 return common.InitAndroidModule(module, common.DeviceSupported, "both",
943 &module.properties, &module.unused)
944}
945
946func (*ccObject) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
947 // object files can't have any dynamic dependencies
948 return nil
949}
950
951func (c *ccObject) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
952 deps, flags := c.ccBase.collectDeps(ctx, flags)
953 ctx.VisitDirectDeps(func(m blueprint.Module) {
954 if obj, ok := m.(*ccObject); ok {
955 deps.objFiles = append(deps.objFiles, obj.outputFile())
956 } else {
957 ctx.ModuleErrorf("Unknown module type for dependency %q", ctx.OtherModuleName(m))
958 }
959 })
960
961 return deps, flags
962}
963
964func (c *ccObject) compileModule(ctx common.AndroidModuleContext,
965 flags ccFlags, deps ccDeps, objFiles []string) {
966
967 objFiles = append(objFiles, deps.objFiles...)
968
969 var outputFile string
970 if len(objFiles) == 1 {
971 outputFile = objFiles[0]
972 } else {
973 outputFile = filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+".o")
974 TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
975 }
976
977 c.out = outputFile
978
979 ctx.CheckbuildFile(outputFile)
980}
981
982func (c *ccObject) outputFile() string {
983 return c.out
984}
985
986//
987// Executables
988//
989
990type ccBinary struct {
991 ccDynamic
992 binaryProperties binaryProperties
993}
994
995type binaryProperties struct {
996 // static_executable: compile executable with -static
997 Static_executable bool
998
999 // stem: set the name of the output
1000 Stem string `android:"arch_variant"`
1001
1002 // prefix_symbols: if set, add an extra objcopy --prefix-symbols= step
1003 Prefix_symbols string
1004}
1005
1006func (c *ccBinary) getStem(ctx common.AndroidModuleContext) string {
1007 if c.binaryProperties.Stem != "" {
1008 return c.binaryProperties.Stem
1009 }
1010 return ctx.ModuleName()
1011}
1012
1013func (c *ccBinary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
1014 deps := c.ccDynamic.AndroidDynamicDependencies(ctx)
1015 if c.HostOrDevice().Device() {
1016 if c.binaryProperties.Static_executable {
1017 deps = append(deps, "crtbegin_static", "crtend_android")
1018 } else {
1019 deps = append(deps, "crtbegin_dynamic", "crtend_android")
1020 }
1021 }
1022 return deps
1023}
1024
1025func NewCCBinary() (blueprint.Module, []interface{}) {
1026 module := &ccBinary{}
1027 module.module = module
1028
1029 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
1030 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "first", &module.properties,
1031 &module.unused, &module.binaryProperties)
1032}
1033
1034func (c *ccBinary) moduleTypeCflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
1035 return []string{"-fpie"}
1036}
1037
1038func (c *ccBinary) moduleTypeLdflags(ctx common.AndroidModuleContext, toolchain toolchain) []string {
1039 if ctx.Arch().HostOrDevice.Device() {
1040 linker := "/system/bin/linker"
1041 if toolchain.Is64Bit() {
1042 linker = "/system/bin/linker64"
1043 }
1044
1045 return []string{
1046 "-nostdlib",
1047 "-Bdynamic",
1048 fmt.Sprintf("-Wl,-dynamic-linker,%s", linker),
1049 "-Wl,--gc-sections",
1050 "-Wl,-z,nocopyreloc",
1051 }
1052 }
1053
1054 return nil
1055}
1056
1057func (c *ccBinary) compileModule(ctx common.AndroidModuleContext,
1058 flags ccFlags, deps ccDeps, objFiles []string) {
1059
1060 if !c.binaryProperties.Static_executable && inList("libc", c.properties.Static_libs) {
1061 ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
1062 "from static libs or set static_executable: true")
1063 }
1064
1065 outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx))
1066
Colin Cross77b00fa2015-03-16 16:15:49 -07001067 TransformObjToDynamicBinary(ctx, objFiles, deps.sharedLibs, deps.staticLibs,
1068 deps.lateStaticLibs, deps.wholeStaticLibs, deps.crtBegin, deps.crtEnd,
1069 ccFlagsToBuilderFlags(flags), outputFile)
Colin Cross3f40fa42015-01-30 17:27:36 -08001070
1071 ctx.InstallFile("bin", outputFile)
1072}
1073
1074//
1075// Static library
1076//
1077
1078func NewCCLibraryStatic() (blueprint.Module, []interface{}) {
1079 module := &ccLibrary{}
1080 module.module = module
1081 module.libraryProperties.BuildStatic = true
1082
1083 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
1084 &module.properties, &module.unused)
1085}
1086
1087//
1088// Shared libraries
1089//
1090
1091func NewCCLibraryShared() (blueprint.Module, []interface{}) {
1092 module := &ccLibrary{}
1093 module.module = module
1094 module.properties.System_shared_libs = []string{defaultSystemSharedLibraries}
1095 module.libraryProperties.BuildShared = true
1096
1097 return common.InitAndroidModule(module, common.HostAndDeviceSupported, "both",
1098 &module.properties, &module.unused)
1099}
1100
1101//
1102// Host static library
1103//
1104
1105func NewCCLibraryHostStatic() (blueprint.Module, []interface{}) {
1106 module := &ccLibrary{}
1107 module.module = module
1108 module.libraryProperties.BuildStatic = true
1109
1110 return common.InitAndroidModule(module, common.HostSupported, "both",
1111 &module.properties, &module.unused)
1112}
1113
1114//
1115// Host Shared libraries
1116//
1117
1118func NewCCLibraryHostShared() (blueprint.Module, []interface{}) {
1119 module := &ccLibrary{}
1120 module.module = module
1121 module.libraryProperties.BuildShared = true
1122
1123 return common.InitAndroidModule(module, common.HostSupported, "both",
1124 &module.properties, &module.unused)
1125}
1126
1127//
1128// Host Binaries
1129//
1130
1131func NewCCBinaryHost() (blueprint.Module, []interface{}) {
1132 module := &ccBinary{}
1133 module.module = module
1134
1135 return common.InitAndroidModule(module, common.HostSupported, "first",
1136 &module.properties, &module.unused)
1137}
1138
1139//
1140// Device libraries shipped with gcc
1141//
1142
1143type toolchainLibrary struct {
1144 ccLibrary
1145}
1146
1147func (*toolchainLibrary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
1148 // toolchain libraries can't have any dependencies
1149 return nil
1150}
1151
1152func (*toolchainLibrary) collectDeps(ctx common.AndroidModuleContext, flags ccFlags) (ccDeps, ccFlags) {
1153 // toolchain libraries can't have any dependencies
1154 return ccDeps{}, flags
1155}
1156
1157func NewToolchainLibrary() (blueprint.Module, []interface{}) {
1158 module := &toolchainLibrary{}
1159 module.module = module
1160 module.libraryProperties.BuildStatic = true
1161
1162 return common.InitAndroidModule(module, common.DeviceSupported, "both")
1163}
1164
1165func (c *toolchainLibrary) compileModule(ctx common.AndroidModuleContext,
1166 flags ccFlags, deps ccDeps, objFiles []string) {
1167
1168 libName := ctx.ModuleName() + staticLibraryExtension
1169 outputFile := filepath.Join(common.ModuleOutDir(ctx), libName)
1170
1171 CopyGccLib(ctx, libName, ccFlagsToBuilderFlags(flags), outputFile)
1172
1173 c.out = outputFile
1174
1175 ctx.CheckbuildFile(outputFile)
1176}
1177
1178func LinkageMutator(mctx blueprint.EarlyMutatorContext) {
1179 if c, ok := mctx.Module().(*ccLibrary); ok {
1180 var modules []blueprint.Module
1181 if c.libraryProperties.BuildStatic && c.libraryProperties.BuildShared {
1182 modules = mctx.CreateLocalVariations("static", "shared")
1183 modules[0].(*ccLibrary).libraryProperties.IsStatic = true
1184 modules[1].(*ccLibrary).libraryProperties.IsShared = true
1185 } else if c.libraryProperties.BuildStatic {
1186 modules = mctx.CreateLocalVariations("static")
1187 modules[0].(*ccLibrary).libraryProperties.IsStatic = true
1188 } else if c.libraryProperties.BuildShared {
1189 modules = mctx.CreateLocalVariations("shared")
1190 modules[0].(*ccLibrary).libraryProperties.IsShared = true
1191 } else {
1192 panic("ccLibrary not static or shared")
1193 }
1194 primary := modules[0].(*ccLibrary)
1195 for _, m := range modules {
1196 m.(*ccLibrary).primary = primary
1197 if m != primary {
1198 m.(*ccLibrary).properties.SkipCompileObjs = true
1199 }
1200 }
1201 } else if _, ok := mctx.Module().(*toolchainLibrary); ok {
1202 mctx.CreateLocalVariations("static")
1203 }
1204}