blob: 5b7ea8b8bb716ddff6c63aef45ab5e7ebfe8e427 [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
139 flags.Nocrt = Bool(linker.Properties.Nocrt)
140
141 if !ctx.noDefaultCompilerFlags() {
142 if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
143 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
144 }
145
146 if flags.Clang {
147 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
148 } else {
149 flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
150 }
151
152 if ctx.Host() {
153 CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
154
155 flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
156 }
157 }
158
159 CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
160
161 flags.LdFlags = append(flags.LdFlags, linker.Properties.Ldflags...)
162
163 if ctx.Host() && !linker.static() {
164 rpath_prefix := `\$$ORIGIN/`
165 if ctx.Darwin() {
166 rpath_prefix = "@loader_path/"
167 }
168
169 for _, rpath := range linker.dynamicProperties.RunPaths {
170 flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
171 }
172 }
173
174 if flags.Clang {
175 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
176 } else {
177 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
178 }
179
180 return flags
181}
182
183func (linker *baseLinker) static() bool {
184 return linker.dynamicProperties.VariantIsStatic
185}
186
187func (linker *baseLinker) staticBinary() bool {
188 return linker.dynamicProperties.VariantIsStaticBinary
189}
190
191func (linker *baseLinker) setStatic(static bool) {
192 linker.dynamicProperties.VariantIsStatic = static
193}
194
195func (linker *baseLinker) isDependencyRoot() bool {
196 return false
197}
198
199type baseLinkerInterface interface {
200 // Returns true if the build options for the module have selected a static or shared build
201 buildStatic() bool
202 buildShared() bool
203
204 // Sets whether a specific variant is static or shared
205 setStatic(bool)
206
207 // Returns whether a specific variant is a static library or binary
208 static() bool
209
210 // Returns whether a module is a static binary
211 staticBinary() bool
212
213 // Returns true for dependency roots (binaries)
214 // TODO(ccross): also handle dlopenable libraries
215 isDependencyRoot() bool
216}