blob: 976775593badebefede8aff7848eb042d0826585 [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
17// This file contains the basic functionality for linking against static libraries and shared
18// libraries. Final linking into libraries or executables is handled in library.go, binary.go, etc.
19
20type BaseLinkerProperties struct {
21 // list of modules whose object files should be linked into this module
22 // in their entirety. For static library modules, all of the .o files from the intermediate
23 // directory of the dependency will be linked into this modules .a file. For a shared library,
24 // the dependency's .a file will be linked into this module using -Wl,--whole-archive.
25 Whole_static_libs []string `android:"arch_variant,variant_prepend"`
26
27 // list of modules that should be statically linked into this module.
28 Static_libs []string `android:"arch_variant,variant_prepend"`
29
30 // list of modules that should be dynamically linked into this module.
31 Shared_libs []string `android:"arch_variant"`
32
33 // list of module-specific flags that will be used for all link steps
34 Ldflags []string `android:"arch_variant"`
35
36 // don't insert default compiler flags into asflags, cflags,
37 // cppflags, conlyflags, ldflags, or include_dirs
38 No_default_compiler_flags *bool
39
40 // list of system libraries that will be dynamically linked to
41 // shared library and executable modules. If unset, generally defaults to libc
42 // and libm. Set to [] to prevent linking against libc and libm.
43 System_shared_libs []string
44
45 // allow the module to contain undefined symbols. By default,
46 // modules cannot contain undefined symbols that are not satisified by their immediate
47 // dependencies. Set this flag to true to remove --no-undefined from the linker flags.
48 // This flag should only be necessary for compiling low-level libraries like libc.
49 Allow_undefined_symbols *bool
50
51 // don't link in libgcc.a
52 No_libgcc *bool
53
54 // -l arguments to pass to linker for host-provided shared libraries
55 Host_ldlibs []string `android:"arch_variant"`
56
57 // list of shared libraries to re-export include directories from. Entries must be
58 // present in shared_libs.
59 Export_shared_lib_headers []string `android:"arch_variant"`
60
61 // list of static libraries to re-export include directories from. Entries must be
62 // present in static_libs.
63 Export_static_lib_headers []string `android:"arch_variant"`
64
65 // don't link in crt_begin and crt_end. This flag should only be necessary for
66 // compiling crt or libc.
67 Nocrt *bool `android:"arch_variant"`
68}
69
70// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
71type baseLinker struct {
72 Properties BaseLinkerProperties
73 dynamicProperties struct {
74 VariantIsShared bool `blueprint:"mutated"`
75 VariantIsStatic bool `blueprint:"mutated"`
76 VariantIsStaticBinary bool `blueprint:"mutated"`
77 RunPaths []string `blueprint:"mutated"`
78 }
79}
80
81func (linker *baseLinker) appendLdflags(flags []string) {
82 linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
83}
84
Colin Cross42742b82016-08-01 13:20:05 -070085func (linker *baseLinker) linkerInit(ctx BaseModuleContext) {
Colin Cross4d9c2d12016-07-29 12:48:20 -070086 if ctx.toolchain().Is64Bit() {
87 linker.dynamicProperties.RunPaths = []string{"../lib64", "lib64"}
88 } else {
89 linker.dynamicProperties.RunPaths = []string{"../lib", "lib"}
90 }
91}
92
Colin Cross42742b82016-08-01 13:20:05 -070093func (linker *baseLinker) linkerProps() []interface{} {
Colin Cross4d9c2d12016-07-29 12:48:20 -070094 return []interface{}{&linker.Properties, &linker.dynamicProperties}
95}
96
Colin Cross42742b82016-08-01 13:20:05 -070097func (linker *baseLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
Colin Cross4d9c2d12016-07-29 12:48:20 -070098 deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
99 deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
100 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
101
102 deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
103 deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
104
105 if !ctx.sdk() && ctx.ModuleName() != "libcompiler_rt-extras" {
106 deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
107 }
108
109 if ctx.Device() {
110 // libgcc and libatomic have to be last on the command line
111 deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
112 if !Bool(linker.Properties.No_libgcc) {
113 deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
114 }
115
116 if !linker.static() {
117 if linker.Properties.System_shared_libs != nil {
118 deps.LateSharedLibs = append(deps.LateSharedLibs,
119 linker.Properties.System_shared_libs...)
120 } else if !ctx.sdk() {
121 deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm")
122 }
123 }
124
125 if ctx.sdk() {
126 deps.SharedLibs = append(deps.SharedLibs,
127 "libc",
128 "libm",
129 )
130 }
131 }
132
133 return deps
134}
135
Colin Cross42742b82016-08-01 13:20:05 -0700136func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700137 toolchain := ctx.toolchain()
138
Colin Cross4d9c2d12016-07-29 12:48:20 -0700139 if !ctx.noDefaultCompilerFlags() {
140 if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
141 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
142 }
143
144 if flags.Clang {
145 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
146 } else {
147 flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
148 }
149
150 if ctx.Host() {
151 CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
152
153 flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
154 }
155 }
156
157 CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
158
159 flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
160
161 if ctx.Host() && !linker.static() {
162 rpath_prefix := `\$$ORIGIN/`
163 if ctx.Darwin() {
164 rpath_prefix = "@loader_path/"
165 }
166
167 for _, rpath := range linker.dynamicProperties.RunPaths {
168 flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
169 }
170 }
171
172 if flags.Clang {
173 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
174 } else {
175 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
176 }
177
178 return flags
179}
180
181func (linker *baseLinker) static() bool {
182 return linker.dynamicProperties.VariantIsStatic
183}
184
185func (linker *baseLinker) staticBinary() bool {
186 return linker.dynamicProperties.VariantIsStaticBinary
187}
188
189func (linker *baseLinker) setStatic(static bool) {
190 linker.dynamicProperties.VariantIsStatic = static
191}
192
193func (linker *baseLinker) isDependencyRoot() bool {
194 return false
195}
196
197type baseLinkerInterface interface {
198 // Returns true if the build options for the module have selected a static or shared build
199 buildStatic() bool
200 buildShared() bool
201
202 // Sets whether a specific variant is static or shared
203 setStatic(bool)
204
205 // Returns whether a specific variant is a static library or binary
206 static() bool
207
208 // Returns whether a module is a static binary
209 staticBinary() bool
210
211 // Returns true for dependency roots (binaries)
212 // TODO(ccross): also handle dlopenable libraries
213 isDependencyRoot() bool
214}