blob: fd64cdaf08297f81f34692a5a8f7a4643f43f670 [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 "github.com/google/blueprint"
19
20 "android/soong"
21 "android/soong/android"
22)
23
24type BinaryLinkerProperties struct {
25 // compile executable with -static
26 Static_executable *bool `android:"arch_variant"`
27
28 // set the name of the output
29 Stem string `android:"arch_variant"`
30
31 // append to the name of the output
32 Suffix string `android:"arch_variant"`
33
34 // if set, add an extra objcopy --prefix-symbols= step
35 Prefix_symbols string
36}
37
38func init() {
39 soong.RegisterModuleType("cc_binary", binaryFactory)
40 soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
41}
42
43// Module factory for binaries
44func binaryFactory() (blueprint.Module, []interface{}) {
45 module := NewBinary(android.HostAndDeviceSupported)
46 return module.Init()
47}
48
49// Module factory for host binaries
50func binaryHostFactory() (blueprint.Module, []interface{}) {
51 module := NewBinary(android.HostSupported)
52 return module.Init()
53}
54
55//
56// Executables
57//
58
59type binaryLinker struct {
60 baseLinker
61 stripper
62
63 Properties BinaryLinkerProperties
64
65 hostToolPath android.OptionalPath
66}
67
68var _ linker = (*binaryLinker)(nil)
69
Colin Cross42742b82016-08-01 13:20:05 -070070func (binary *binaryLinker) linkerProps() []interface{} {
71 return append(binary.baseLinker.linkerProps(),
Colin Cross4d9c2d12016-07-29 12:48:20 -070072 &binary.Properties,
73 &binary.stripper.StripProperties)
74
75}
76
77func (binary *binaryLinker) buildStatic() bool {
78 return binary.baseLinker.staticBinary()
79}
80
81func (binary *binaryLinker) buildShared() bool {
82 return !binary.baseLinker.staticBinary()
83}
84
85func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
86 stem := ctx.ModuleName()
87 if binary.Properties.Stem != "" {
88 stem = binary.Properties.Stem
89 }
90
91 return stem + binary.Properties.Suffix
92}
93
Colin Cross42742b82016-08-01 13:20:05 -070094func (binary *binaryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
95 deps = binary.baseLinker.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -070096 if ctx.Device() {
97 if !Bool(binary.baseLinker.Properties.Nocrt) {
98 if !ctx.sdk() {
99 if binary.buildStatic() {
100 deps.CrtBegin = "crtbegin_static"
101 } else {
102 deps.CrtBegin = "crtbegin_dynamic"
103 }
104 deps.CrtEnd = "crtend_android"
105 } else {
106 if binary.buildStatic() {
107 deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
108 } else {
109 if Bool(binary.Properties.Static_executable) {
110 deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
111 } else {
112 deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
113 }
114 deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
115 }
116 }
117 }
118
119 if binary.buildStatic() {
120 if inList("libc++_static", deps.StaticLibs) {
121 deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
122 }
123 // static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
124 // --start-group/--end-group along with libgcc. If they are in deps.StaticLibs,
125 // move them to the beginning of deps.LateStaticLibs
126 var groupLibs []string
127 deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
128 []string{"libc", "libc_nomalloc", "libcompiler_rt"})
129 deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
130 }
131 }
132
133 if binary.buildShared() && inList("libc", deps.StaticLibs) {
134 ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
135 "from static libs or set static_executable: true")
136 }
137 return deps
138}
139
140func (*binaryLinker) installable() bool {
141 return true
142}
143
144func (binary *binaryLinker) isDependencyRoot() bool {
145 return true
146}
147
148func NewBinary(hod android.HostOrDeviceSupported) *Module {
149 module := newModule(hod, android.MultilibFirst)
150 module.compiler = &baseCompiler{}
151 module.linker = &binaryLinker{}
152 module.installer = &baseInstaller{
153 dir: "bin",
154 }
155 return module
156}
157
Colin Cross42742b82016-08-01 13:20:05 -0700158func (binary *binaryLinker) linkerInit(ctx BaseModuleContext) {
159 binary.baseLinker.linkerInit(ctx)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700160
161 static := Bool(binary.Properties.Static_executable)
162 if ctx.Host() {
163 if ctx.Os() == android.Linux {
164 if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
165 static = true
166 }
167 } else {
168 // Static executables are not supported on Darwin or Windows
169 static = false
170 }
171 }
172 if static {
173 binary.dynamicProperties.VariantIsStatic = true
174 binary.dynamicProperties.VariantIsStaticBinary = true
175 }
176}
177
Colin Cross42742b82016-08-01 13:20:05 -0700178func (binary *binaryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
179 flags = binary.baseLinker.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700180
181 if ctx.Host() && !binary.staticBinary() {
182 flags.LdFlags = append(flags.LdFlags, "-pie")
183 if ctx.Os() == android.Windows {
184 flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
185 }
186 }
187
188 // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
189 // all code is position independent, and then those warnings get promoted to
190 // errors.
191 if ctx.Os() != android.Windows {
192 flags.CFlags = append(flags.CFlags, "-fpie")
193 }
194
195 if ctx.Device() {
196 if binary.buildStatic() {
197 // Clang driver needs -static to create static executable.
198 // However, bionic/linker uses -shared to overwrite.
199 // Linker for x86 targets does not allow coexistance of -static and -shared,
200 // so we add -static only if -shared is not used.
201 if !inList("-shared", flags.LdFlags) {
202 flags.LdFlags = append(flags.LdFlags, "-static")
203 }
204
205 flags.LdFlags = append(flags.LdFlags,
206 "-nostdlib",
207 "-Bstatic",
208 "-Wl,--gc-sections",
209 )
210
211 } else {
212 if flags.DynamicLinker == "" {
213 flags.DynamicLinker = "/system/bin/linker"
214 if flags.Toolchain.Is64Bit() {
215 flags.DynamicLinker += "64"
216 }
217 }
218
219 flags.LdFlags = append(flags.LdFlags,
220 "-pie",
221 "-nostdlib",
222 "-Bdynamic",
223 "-Wl,--gc-sections",
224 "-Wl,-z,nocopyreloc",
225 )
226 }
227 } else {
228 if binary.staticBinary() {
229 flags.LdFlags = append(flags.LdFlags, "-static")
230 }
231 if ctx.Darwin() {
232 flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
233 }
234 }
235
236 return flags
237}
238
239func (binary *binaryLinker) link(ctx ModuleContext,
240 flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
241
242 fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
243 outputFile := android.PathForModuleOut(ctx, fileName)
244 ret := outputFile
245 if ctx.Os().Class == android.Host {
246 binary.hostToolPath = android.OptionalPathForPath(outputFile)
247 }
248
249 var linkerDeps android.Paths
250
251 sharedLibs := deps.SharedLibs
252 sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
253
254 if flags.DynamicLinker != "" {
255 flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
256 }
257
258 builderFlags := flagsToBuilderFlags(flags)
259
260 if binary.stripper.needsStrip(ctx) {
261 strippedOutputFile := outputFile
262 outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
263 binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
264 }
265
266 if binary.Properties.Prefix_symbols != "" {
267 afterPrefixSymbols := outputFile
268 outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
269 TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
270 flagsToBuilderFlags(flags), afterPrefixSymbols)
271 }
272
273 TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
274 deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
275 builderFlags, outputFile)
276
277 return ret
278}
279
280func (binary *binaryLinker) HostToolPath() android.OptionalPath {
281 return binary.hostToolPath
282}