blob: 14ceb28995318b6fbf7b38b42e2d315bd5b68123 [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",
218 //"-read_only_relocs suppress",
219 "-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
398 TransformObjToDynamicBinary(ctx, objFiles, sharedLibs,
399 deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
400 linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile)
401
402 return ret
403}
404
Colin Crossb916a382016-07-29 17:28:03 -0700405func (library *libraryDecorator) link(ctx ModuleContext,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700406 flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
407
408 objFiles = append(objFiles, deps.ObjFiles...)
409
410 var out android.Path
411 if library.static() {
412 out = library.linkStatic(ctx, flags, deps, objFiles)
413 } else {
414 out = library.linkShared(ctx, flags, deps, objFiles)
415 }
416
417 library.exportIncludes(ctx, "-I")
418 library.reexportFlags(deps.ReexportedFlags)
419
420 return out
421}
422
Colin Crossb916a382016-07-29 17:28:03 -0700423func (library *libraryDecorator) buildStatic() bool {
424 return library.Properties.BuildStatic &&
Colin Cross4d9c2d12016-07-29 12:48:20 -0700425 (library.Properties.Static.Enabled == nil || *library.Properties.Static.Enabled)
426}
427
Colin Crossb916a382016-07-29 17:28:03 -0700428func (library *libraryDecorator) buildShared() bool {
429 return library.Properties.BuildShared &&
Colin Cross4d9c2d12016-07-29 12:48:20 -0700430 (library.Properties.Shared.Enabled == nil || *library.Properties.Shared.Enabled)
431}
432
Colin Crossb916a382016-07-29 17:28:03 -0700433func (library *libraryDecorator) getWholeStaticMissingDeps() []string {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700434 return library.wholeStaticMissingDeps
435}
436
Colin Crossb916a382016-07-29 17:28:03 -0700437func (library *libraryDecorator) objs() android.Paths {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700438 return library.objFiles
439}
440
Colin Crossb916a382016-07-29 17:28:03 -0700441func (library *libraryDecorator) reuseObjs() android.Paths {
442 return library.reuseObjFiles
Colin Cross4d9c2d12016-07-29 12:48:20 -0700443}
444
Colin Crossb916a382016-07-29 17:28:03 -0700445func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
446 if !ctx.static() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700447 library.baseInstaller.install(ctx, file)
448 }
449}
450
Colin Crossb916a382016-07-29 17:28:03 -0700451func (library *libraryDecorator) static() bool {
452 return library.Properties.VariantIsStatic
Colin Cross4d9c2d12016-07-29 12:48:20 -0700453}
454
Colin Crossb916a382016-07-29 17:28:03 -0700455func (library *libraryDecorator) setStatic(static bool) {
456 library.Properties.VariantIsStatic = static
457}
458
459func NewLibrary(hod android.HostOrDeviceSupported, shared, static bool) (*Module, *libraryDecorator) {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700460 module := newModule(hod, android.MultilibBoth)
461
Colin Crossb916a382016-07-29 17:28:03 -0700462 library := &libraryDecorator{
463 Properties: LibraryProperties{
464 BuildShared: shared,
465 BuildStatic: static,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700466 },
Colin Crossb916a382016-07-29 17:28:03 -0700467 baseCompiler: NewBaseCompiler(),
468 baseLinker: NewBaseLinker(),
469 baseInstaller: NewBaseInstaller("lib", "lib64", InstallInSystem),
470 sanitize: module.sanitize,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700471 }
472
Colin Crossb916a382016-07-29 17:28:03 -0700473 module.compiler = library
474 module.linker = library
475 module.installer = library
476
477 return module, library
478}
479
480func linkageMutator(mctx android.BottomUpMutatorContext) {
481 if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
482 if library, ok := m.linker.(libraryInterface); ok {
483 var modules []blueprint.Module
484 if library.buildStatic() && library.buildShared() {
485 modules = mctx.CreateLocalVariations("static", "shared")
486 static := modules[0].(*Module)
487 shared := modules[1].(*Module)
488
489 static.linker.(libraryInterface).setStatic(true)
490 shared.linker.(libraryInterface).setStatic(false)
491
492 if staticCompiler, ok := static.compiler.(*libraryDecorator); ok {
493 sharedCompiler := shared.compiler.(*libraryDecorator)
494 if len(staticCompiler.Properties.Static.Cflags) == 0 &&
495 len(sharedCompiler.Properties.Shared.Cflags) == 0 {
496 // Optimize out compiling common .o files twice for static+shared libraries
497 mctx.AddInterVariantDependency(reuseObjTag, shared, static)
498 sharedCompiler.baseCompiler.Properties.Srcs = nil
499 sharedCompiler.baseCompiler.Properties.Generated_sources = nil
500 }
501 }
502 } else if library.buildStatic() {
503 modules = mctx.CreateLocalVariations("static")
504 modules[0].(*Module).linker.(libraryInterface).setStatic(true)
505 } else if library.buildShared() {
506 modules = mctx.CreateLocalVariations("shared")
507 modules[0].(*Module).linker.(libraryInterface).setStatic(false)
508 }
509 }
510 }
Colin Cross4d9c2d12016-07-29 12:48:20 -0700511}