blob: 5119c90d03eeaa8ee9cd895ba03164f11ae24961 [file] [log] [blame]
Colin Cross4d9c2d12016-07-29 12:48:20 -07001// 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 "strings"
19
20 "github.com/google/blueprint"
21
22 "android/soong"
23 "android/soong/android"
24)
25
Colin Crossb916a382016-07-29 17:28:03 -070026type LibraryProperties struct {
Colin Cross4d9c2d12016-07-29 12:48:20 -070027 Static struct {
28 Srcs []string `android:"arch_variant"`
29 Exclude_srcs []string `android:"arch_variant"`
30 Cflags []string `android:"arch_variant"`
Colin Cross4d9c2d12016-07-29 12:48:20 -070031
Colin Cross4d9c2d12016-07-29 12:48:20 -070032 Enabled *bool `android:"arch_variant"`
33 Whole_static_libs []string `android:"arch_variant"`
34 Static_libs []string `android:"arch_variant"`
35 Shared_libs []string `android:"arch_variant"`
36 } `android:"arch_variant"`
37 Shared struct {
Colin Crossb916a382016-07-29 17:28:03 -070038 Srcs []string `android:"arch_variant"`
39 Exclude_srcs []string `android:"arch_variant"`
40 Cflags []string `android:"arch_variant"`
41
Colin Cross4d9c2d12016-07-29 12:48:20 -070042 Enabled *bool `android:"arch_variant"`
43 Whole_static_libs []string `android:"arch_variant"`
44 Static_libs []string `android:"arch_variant"`
45 Shared_libs []string `android:"arch_variant"`
46 } `android:"arch_variant"`
47
48 // local file name to pass to the linker as --version_script
49 Version_script *string `android:"arch_variant"`
50 // local file name to pass to the linker as -unexported_symbols_list
51 Unexported_symbols_list *string `android:"arch_variant"`
52 // local file name to pass to the linker as -force_symbols_not_weak_list
53 Force_symbols_not_weak_list *string `android:"arch_variant"`
54 // local file name to pass to the linker as -force_symbols_weak_list
55 Force_symbols_weak_list *string `android:"arch_variant"`
56
57 // rename host libraries to prevent overlap with system installed libraries
58 Unique_host_soname *bool
59
60 VariantName string `blueprint:"mutated"`
Colin Crossb916a382016-07-29 17:28:03 -070061
62 // Build a static variant
63 BuildStatic bool `blueprint:"mutated"`
64 // Build a shared variant
65 BuildShared bool `blueprint:"mutated"`
66 // This variant is shared
67 VariantIsShared bool `blueprint:"mutated"`
68 // This variant is static
69 VariantIsStatic bool `blueprint:"mutated"`
70}
71
72type FlagExporterProperties struct {
73 // list of directories relative to the Blueprints file that will
74 // be added to the include path using -I for any module that links against this module
75 Export_include_dirs []string `android:"arch_variant"`
Colin Cross4d9c2d12016-07-29 12:48:20 -070076}
77
78func init() {
79 soong.RegisterModuleType("cc_library_static", libraryStaticFactory)
80 soong.RegisterModuleType("cc_library_shared", librarySharedFactory)
81 soong.RegisterModuleType("cc_library", libraryFactory)
82 soong.RegisterModuleType("cc_library_host_static", libraryHostStaticFactory)
83 soong.RegisterModuleType("cc_library_host_shared", libraryHostSharedFactory)
84}
85
86// Module factory for combined static + shared libraries, device by default but with possible host
87// support
88func libraryFactory() (blueprint.Module, []interface{}) {
Colin Crossb916a382016-07-29 17:28:03 -070089 module, _ := NewLibrary(android.HostAndDeviceSupported, true, true)
Colin Cross4d9c2d12016-07-29 12:48:20 -070090 return module.Init()
91}
92
93// Module factory for static libraries
94func libraryStaticFactory() (blueprint.Module, []interface{}) {
Colin Crossb916a382016-07-29 17:28:03 -070095 module, _ := NewLibrary(android.HostAndDeviceSupported, false, true)
Colin Cross4d9c2d12016-07-29 12:48:20 -070096 return module.Init()
97}
98
99// Module factory for shared libraries
100func librarySharedFactory() (blueprint.Module, []interface{}) {
Colin Crossb916a382016-07-29 17:28:03 -0700101 module, _ := NewLibrary(android.HostAndDeviceSupported, true, false)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700102 return module.Init()
103}
104
105// Module factory for host static libraries
106func libraryHostStaticFactory() (blueprint.Module, []interface{}) {
Colin Crossb916a382016-07-29 17:28:03 -0700107 module, _ := NewLibrary(android.HostSupported, false, true)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700108 return module.Init()
109}
110
111// Module factory for host shared libraries
112func libraryHostSharedFactory() (blueprint.Module, []interface{}) {
Colin Crossb916a382016-07-29 17:28:03 -0700113 module, _ := NewLibrary(android.HostSupported, true, false)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700114 return module.Init()
115}
116
117type flagExporter struct {
118 Properties FlagExporterProperties
119
120 flags []string
121}
122
123func (f *flagExporter) exportIncludes(ctx ModuleContext, inc string) {
124 includeDirs := android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
125 for _, dir := range includeDirs.Strings() {
126 f.flags = append(f.flags, inc+dir)
127 }
128}
129
130func (f *flagExporter) reexportFlags(flags []string) {
131 f.flags = append(f.flags, flags...)
132}
133
134func (f *flagExporter) exportedFlags() []string {
135 return f.flags
136}
137
138type exportedFlagsProducer interface {
139 exportedFlags() []string
140}
141
142var _ exportedFlagsProducer = (*flagExporter)(nil)
143
Colin Crossb916a382016-07-29 17:28:03 -0700144// libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific
145// functionality: static vs. shared linkage, reusing object files for shared libraries
146type libraryDecorator struct {
147 Properties LibraryProperties
Colin Cross4d9c2d12016-07-29 12:48:20 -0700148
149 // For reusing static library objects for shared library
150 reuseObjFiles android.Paths
Colin Cross4d9c2d12016-07-29 12:48:20 -0700151
Colin Cross4d9c2d12016-07-29 12:48:20 -0700152 flagExporter
153 stripper
154
Colin Cross4d9c2d12016-07-29 12:48:20 -0700155 // If we're used as a whole_static_lib, our missing dependencies need
156 // to be given
157 wholeStaticMissingDeps []string
158
159 // For whole_static_libs
160 objFiles android.Paths
161
162 // Uses the module's name if empty, but can be overridden. Does not include
163 // shlib suffix.
164 libName string
Colin Crossb916a382016-07-29 17:28:03 -0700165
166 sanitize *sanitize
167
168 // Decorated interafaces
169 *baseCompiler
170 *baseLinker
171 *baseInstaller
Colin Cross4d9c2d12016-07-29 12:48:20 -0700172}
173
Colin Crossb916a382016-07-29 17:28:03 -0700174func (library *libraryDecorator) linkerProps() []interface{} {
175 var props []interface{}
176 props = append(props, library.baseLinker.linkerProps()...)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700177 return append(props,
178 &library.Properties,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700179 &library.flagExporter.Properties,
180 &library.stripper.StripProperties)
181}
182
Colin Crossb916a382016-07-29 17:28:03 -0700183func (library *libraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
Colin Cross42742b82016-08-01 13:20:05 -0700184 flags = library.baseLinker.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700185
Colin Crossb916a382016-07-29 17:28:03 -0700186 // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
187 // all code is position independent, and then those warnings get promoted to
188 // errors.
189 if ctx.Os() != android.Windows {
190 flags.CFlags = append(flags.CFlags, "-fPIC")
191 }
192
193 if library.static() {
194 flags.CFlags = append(flags.CFlags, library.Properties.Static.Cflags...)
195 } else {
196 flags.CFlags = append(flags.CFlags, library.Properties.Shared.Cflags...)
197 }
198
Colin Cross4d9c2d12016-07-29 12:48:20 -0700199 if !library.static() {
200 libName := library.getLibName(ctx)
201 // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
202 sharedFlag := "-Wl,-shared"
203 if flags.Clang || ctx.Host() {
204 sharedFlag = "-shared"
205 }
206 var f []string
207 if ctx.Device() {
208 f = append(f,
209 "-nostdlib",
210 "-Wl,--gc-sections",
211 )
212 }
213
214 if ctx.Darwin() {
215 f = append(f,
216 "-dynamiclib",
217 "-single_module",
Colin Cross7d82ab72016-08-25 16:54:53 -0700218 "-read_only_relocs suppress",
Colin Cross4d9c2d12016-07-29 12:48:20 -0700219 "-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
220 )
221 } else {
222 f = append(f,
223 sharedFlag,
224 "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
225 }
226
227 flags.LdFlags = append(f, flags.LdFlags...)
228 }
229
230 return flags
231}
232
Colin Crossb916a382016-07-29 17:28:03 -0700233func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
234 var objFiles android.Paths
235
236 objFiles = library.baseCompiler.compile(ctx, flags, deps)
237 library.reuseObjFiles = objFiles
238
239 pathDeps := deps.GeneratedHeaders
240 pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
241
Colin Cross4d9c2d12016-07-29 12:48:20 -0700242 if library.static() {
Colin Crossb916a382016-07-29 17:28:03 -0700243 objFiles = append(objFiles, compileObjs(ctx, flags, android.DeviceStaticLibrary,
244 library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
245 nil, pathDeps)...)
246 } else {
247 objFiles = append(objFiles, compileObjs(ctx, flags, android.DeviceSharedLibrary,
248 library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
249 nil, pathDeps)...)
250 }
251
252 return objFiles
253}
254
255type libraryInterface interface {
256 getWholeStaticMissingDeps() []string
257 static() bool
258 objs() android.Paths
259 reuseObjs() android.Paths
260
261 // Returns true if the build options for the module have selected a static or shared build
262 buildStatic() bool
263 buildShared() bool
264
265 // Sets whether a specific variant is static or shared
266 setStatic(bool)
267}
268
269func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
270 name := library.libName
271 if name == "" {
272 name = ctx.ModuleName()
273 }
274
275 if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
276 if !strings.HasSuffix(name, "-host") {
277 name = name + "-host"
278 }
279 }
280
281 return name + library.Properties.VariantName
282}
283
284func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
285 location := InstallInSystem
286 if library.sanitize.inData() {
287 location = InstallInData
288 }
289 library.baseInstaller.location = location
290
291 library.baseLinker.linkerInit(ctx)
292}
293
294func (library *libraryDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
295 deps = library.baseLinker.linkerDeps(ctx, deps)
296
297 if library.static() {
298 deps.WholeStaticLibs = append(deps.WholeStaticLibs,
299 library.Properties.Static.Whole_static_libs...)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700300 deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
301 deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
302 } else {
303 if ctx.Device() && !Bool(library.baseLinker.Properties.Nocrt) {
304 if !ctx.sdk() {
305 deps.CrtBegin = "crtbegin_so"
306 deps.CrtEnd = "crtend_so"
307 } else {
308 deps.CrtBegin = "ndk_crtbegin_so." + ctx.sdkVersion()
309 deps.CrtEnd = "ndk_crtend_so." + ctx.sdkVersion()
310 }
311 }
312 deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
313 deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
314 deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
315 }
316
317 return deps
318}
319
Colin Crossb916a382016-07-29 17:28:03 -0700320func (library *libraryDecorator) linkStatic(ctx ModuleContext,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700321 flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
322
323 library.objFiles = append(android.Paths{}, deps.WholeStaticLibObjFiles...)
324 library.objFiles = append(library.objFiles, objFiles...)
325
326 outputFile := android.PathForModuleOut(ctx,
327 ctx.ModuleName()+library.Properties.VariantName+staticLibraryExtension)
328
329 if ctx.Darwin() {
330 TransformDarwinObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
331 } else {
332 TransformObjToStaticLib(ctx, library.objFiles, flagsToBuilderFlags(flags), outputFile)
333 }
334
335 library.wholeStaticMissingDeps = ctx.GetMissingDependencies()
336
337 ctx.CheckbuildFile(outputFile)
338
339 return outputFile
340}
341
Colin Crossb916a382016-07-29 17:28:03 -0700342func (library *libraryDecorator) linkShared(ctx ModuleContext,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700343 flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
344
345 var linkerDeps android.Paths
346
347 versionScript := android.OptionalPathForModuleSrc(ctx, library.Properties.Version_script)
348 unexportedSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Unexported_symbols_list)
349 forceNotWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_not_weak_list)
350 forceWeakSymbols := android.OptionalPathForModuleSrc(ctx, library.Properties.Force_symbols_weak_list)
351 if !ctx.Darwin() {
352 if versionScript.Valid() {
353 flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
354 linkerDeps = append(linkerDeps, versionScript.Path())
355 }
356 if unexportedSymbols.Valid() {
357 ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
358 }
359 if forceNotWeakSymbols.Valid() {
360 ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
361 }
362 if forceWeakSymbols.Valid() {
363 ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
364 }
365 } else {
366 if versionScript.Valid() {
367 ctx.PropertyErrorf("version_script", "Not supported on Darwin")
368 }
369 if unexportedSymbols.Valid() {
370 flags.LdFlags = append(flags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
371 linkerDeps = append(linkerDeps, unexportedSymbols.Path())
372 }
373 if forceNotWeakSymbols.Valid() {
374 flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
375 linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
376 }
377 if forceWeakSymbols.Valid() {
378 flags.LdFlags = append(flags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
379 linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
380 }
381 }
382
383 fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
384 outputFile := android.PathForModuleOut(ctx, fileName)
385 ret := outputFile
386
387 builderFlags := flagsToBuilderFlags(flags)
388
389 if library.stripper.needsStrip(ctx) {
390 strippedOutputFile := outputFile
391 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
392 library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
393 }
394
395 sharedLibs := deps.SharedLibs
396 sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
397
Dan Albertd015c4a2016-08-10 14:34:08 -0700398 // TODO(danalbert): Clean this up when soong supports prebuilts.
399 if strings.HasPrefix(ctx.selectedStl(), "ndk_libc++") {
400 libDir := getNdkStlLibDir(ctx, flags.Toolchain, "libc++")
401
402 if strings.HasSuffix(ctx.selectedStl(), "_shared") {
403 deps.StaticLibs = append(deps.StaticLibs,
404 libDir.Join(ctx, "libandroid_support.a"))
405 } else {
406 deps.StaticLibs = append(deps.StaticLibs,
407 libDir.Join(ctx, "libc++abi.a"),
408 libDir.Join(ctx, "libandroid_support.a"))
409 }
410
411 if ctx.Arch().ArchType == android.Arm {
412 deps.StaticLibs = append(deps.StaticLibs,
413 libDir.Join(ctx, "libunwind.a"))
414 }
415 }
416
Colin Cross4d9c2d12016-07-29 12:48:20 -0700417 TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
418 deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
419 linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
420
421 return ret
422}
423
Colin Crossb916a382016-07-29 17:28:03 -0700424func (library *libraryDecorator) link(ctx ModuleContext,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700425 flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
426
427 objFiles = append(objFiles, deps.ObjFiles...)
428
429 var out android.Path
430 if library.static() {
431 out = library.linkStatic(ctx, flags, deps, objFiles)
432 } else {
433 out = library.linkShared(ctx, flags, deps, objFiles)
434 }
435
436 library.exportIncludes(ctx, "-I")
437 library.reexportFlags(deps.ReexportedFlags)
438
439 return out
440}
441
Colin Crossb916a382016-07-29 17:28:03 -0700442func (library *libraryDecorator) buildStatic() bool {
443 return library.Properties.BuildStatic &&
Colin Cross4d9c2d12016-07-29 12:48:20 -0700444 (library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
445}
446
Colin Crossb916a382016-07-29 17:28:03 -0700447func (library *libraryDecorator) buildShared() bool {
448 return library.Properties.BuildShared &&
Colin Cross4d9c2d12016-07-29 12:48:20 -0700449 (library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
450}
451
Colin Crossb916a382016-07-29 17:28:03 -0700452func (library *libraryDecorator) getWholeStaticMissingDeps() []string {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700453 return library.wholeStaticMissingDeps
454}
455
Colin Crossb916a382016-07-29 17:28:03 -0700456func (library *libraryDecorator) objs() android.Paths {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700457 return library.objFiles
458}
459
Colin Crossb916a382016-07-29 17:28:03 -0700460func (library *libraryDecorator) reuseObjs() android.Paths {
461 return library.reuseObjFiles
Colin Cross4d9c2d12016-07-29 12:48:20 -0700462}
463
Colin Crossb916a382016-07-29 17:28:03 -0700464func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
465 if !ctx.static() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700466 library.baseInstaller.install(ctx, file)
467 }
468}
469
Colin Crossb916a382016-07-29 17:28:03 -0700470func (library *libraryDecorator) static() bool {
471 return library.Properties.VariantIsStatic
Colin Cross4d9c2d12016-07-29 12:48:20 -0700472}
473
Colin Crossb916a382016-07-29 17:28:03 -0700474func (library *libraryDecorator) setStatic(static bool) {
475 library.Properties.VariantIsStatic = static
476}
477
478func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) (*Module, *libraryDecorator) {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700479 module := newModule(hod, android.MultilibBoth)
480
Colin Crossb916a382016-07-29 17:28:03 -0700481 library := &libraryDecorator{
482 Properties: LibraryProperties{
483 BuildShared: shared,
484 BuildStatic: static,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700485 },
Colin Crossb916a382016-07-29 17:28:03 -0700486 baseCompiler: NewBaseCompiler(),
487 baseLinker: NewBaseLinker(),
488 baseInstaller: NewBaseInstaller("lib", "lib64", InstallInSystem),
489 sanitize: module.sanitize,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700490 }
491
Colin Crossb916a382016-07-29 17:28:03 -0700492 module.compiler = library
493 module.linker = library
494 module.installer = library
495
496 return module, library
497}
498
499func linkageMutator(mctx android.BottomUpMutatorContext) {
500 if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
501 if library, ok := m.linker.(libraryInterface); ok {
502 var modules []blueprint.Module
503 if library.buildStatic() && library.buildShared() {
504 modules = mctx.CreateLocalVariations("static", "shared")
505 static := modules[0].(*Module)
506 shared := modules[1].(*Module)
507
508 static.linker.(libraryInterface).setStatic(true)
509 shared.linker.(libraryInterface).setStatic(false)
510
511 if staticCompiler, ok := static.compiler.(*libraryDecorator); ok {
512 sharedCompiler := shared.compiler.(*libraryDecorator)
513 if len(staticCompiler.Properties.Static.Cflags) == 0 &&
514 len(sharedCompiler.Properties.Shared.Cflags) == 0 {
515 // Optimize out compiling common .o files twice for static+shared libraries
516 mctx.AddInterVariantDependency(reuseObjTag, shared, static)
517 sharedCompiler.baseCompiler.Properties.Srcs = nil
518 sharedCompiler.baseCompiler.Properties.Generated_sources = nil
519 }
520 }
521 } else if library.buildStatic() {
522 modules = mctx.CreateLocalVariations("static")
523 modules[0].(*Module).linker.(libraryInterface).setStatic(true)
524 } else if library.buildShared() {
525 modules = mctx.CreateLocalVariations("shared")
526 modules[0].(*Module).linker.(libraryInterface).setStatic(false)
527 }
528 }
529 }
Colin Cross4d9c2d12016-07-29 12:48:20 -0700530}