• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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	"android/soong/android"
19	"android/soong/cc/config"
20	"fmt"
21	"strconv"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25)
26
27// This file contains the basic functionality for linking against static libraries and shared
28// libraries.  Final linking into libraries or executables is handled in library.go, binary.go, etc.
29
30type BaseLinkerProperties struct {
31	// list of modules whose object files should be linked into this module
32	// in their entirety.  For static library modules, all of the .o files from the intermediate
33	// directory of the dependency will be linked into this modules .a file.  For a shared library,
34	// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
35	Whole_static_libs []string `android:"arch_variant,variant_prepend"`
36
37	// list of modules that should be statically linked into this module.
38	Static_libs []string `android:"arch_variant,variant_prepend"`
39
40	// list of modules that should be dynamically linked into this module.
41	Shared_libs []string `android:"arch_variant"`
42
43	// list of modules that should only provide headers for this module.
44	Header_libs []string `android:"arch_variant,variant_prepend"`
45
46	// list of module-specific flags that will be used for all link steps
47	Ldflags []string `android:"arch_variant"`
48
49	// list of system libraries that will be dynamically linked to
50	// shared library and executable modules.  If unset, generally defaults to libc,
51	// libm, and libdl.  Set to [] to prevent linking against the defaults.
52	System_shared_libs []string `android:"arch_variant"`
53
54	// allow the module to contain undefined symbols.  By default,
55	// modules cannot contain undefined symbols that are not satisified by their immediate
56	// dependencies.  Set this flag to true to remove --no-undefined from the linker flags.
57	// This flag should only be necessary for compiling low-level libraries like libc.
58	Allow_undefined_symbols *bool `android:"arch_variant"`
59
60	// don't link in libgcc.a
61	No_libgcc *bool
62
63	// don't link in libclang_rt.builtins-*.a
64	No_libcrt *bool `android:"arch_variant"`
65
66	// Use clang lld instead of gnu ld.
67	Use_clang_lld *bool `android:"arch_variant"`
68
69	// -l arguments to pass to linker for host-provided shared libraries
70	Host_ldlibs []string `android:"arch_variant"`
71
72	// list of shared libraries to re-export include directories from. Entries must be
73	// present in shared_libs.
74	Export_shared_lib_headers []string `android:"arch_variant"`
75
76	// list of static libraries to re-export include directories from. Entries must be
77	// present in static_libs.
78	Export_static_lib_headers []string `android:"arch_variant"`
79
80	// list of header libraries to re-export include directories from. Entries must be
81	// present in header_libs.
82	Export_header_lib_headers []string `android:"arch_variant"`
83
84	// list of generated headers to re-export include directories from. Entries must be
85	// present in generated_headers.
86	Export_generated_headers []string `android:"arch_variant"`
87
88	// don't link in crt_begin and crt_end.  This flag should only be necessary for
89	// compiling crt or libc.
90	Nocrt *bool `android:"arch_variant"`
91
92	// group static libraries.  This can resolve missing symbols issues with interdependencies
93	// between static libraries, but it is generally better to order them correctly instead.
94	Group_static_libs *bool `android:"arch_variant"`
95
96	// list of modules that should be installed with this module.  This is similar to 'required'
97	// but '.vendor' suffix will be appended to the module names if the shared libraries have
98	// vendor variants and this module uses VNDK.
99	Runtime_libs []string `android:"arch_variant"`
100
101	Target struct {
102		Vendor struct {
103			// list of shared libs that only should be used to build the vendor
104			// variant of the C/C++ module.
105			Shared_libs []string
106
107			// list of shared libs that should not be used to build the vendor variant
108			// of the C/C++ module.
109			Exclude_shared_libs []string
110
111			// list of static libs that should not be used to build the vendor variant
112			// of the C/C++ module.
113			Exclude_static_libs []string
114
115			// list of header libs that should not be used to build the vendor variant
116			// of the C/C++ module.
117			Exclude_header_libs []string
118
119			// list of runtime libs that should not be installed along with the vendor
120			// variant of the C/C++ module.
121			Exclude_runtime_libs []string
122
123			// version script for this vendor variant
124			Version_script *string `android:"arch_variant"`
125		}
126		Recovery struct {
127			// list of shared libs that only should be used to build the recovery
128			// variant of the C/C++ module.
129			Shared_libs []string
130
131			// list of shared libs that should not be used to build
132			// the recovery variant of the C/C++ module.
133			Exclude_shared_libs []string
134
135			// list of static libs that should not be used to build
136			// the recovery variant of the C/C++ module.
137			Exclude_static_libs []string
138
139			// list of header libs that should not be used to build the recovery variant
140			// of the C/C++ module.
141			Exclude_header_libs []string
142		}
143	}
144
145	// make android::build:GetBuildNumber() available containing the build ID.
146	Use_version_lib *bool `android:"arch_variant"`
147
148	// Generate compact dynamic relocation table, default true.
149	Pack_relocations *bool `android:"arch_variant"`
150
151	// local file name to pass to the linker as --version_script
152	Version_script *string `android:"path,arch_variant"`
153
154	// Local file name to pass to the linker as --symbol-ordering-file
155	Symbol_ordering_file *string `android:"arch_variant"`
156}
157
158func NewBaseLinker(sanitize *sanitize) *baseLinker {
159	return &baseLinker{sanitize: sanitize}
160}
161
162// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
163type baseLinker struct {
164	Properties        BaseLinkerProperties
165	dynamicProperties struct {
166		RunPaths   []string `blueprint:"mutated"`
167		BuildStubs bool     `blueprint:"mutated"`
168	}
169
170	sanitize *sanitize
171}
172
173func (linker *baseLinker) appendLdflags(flags []string) {
174	linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
175}
176
177func (linker *baseLinker) linkerInit(ctx BaseModuleContext) {
178	if ctx.toolchain().Is64Bit() {
179		linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64")
180	} else {
181		linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib")
182	}
183}
184
185func (linker *baseLinker) linkerProps() []interface{} {
186	return []interface{}{&linker.Properties, &linker.dynamicProperties}
187}
188
189func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
190	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
191	deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
192	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
193	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
194	deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...)
195
196	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...)
197	deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
198	deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
199	deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...)
200
201	if Bool(linker.Properties.Use_version_lib) {
202		deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
203	}
204
205	if ctx.useVndk() {
206		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
207		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
208		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
209		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
210		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs)
211		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
212		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
213		deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
214	}
215
216	if ctx.inRecovery() {
217		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Recovery.Shared_libs...)
218		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
219		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
220		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
221		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Recovery.Exclude_header_libs)
222		deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Recovery.Exclude_header_libs)
223		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
224		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
225	}
226
227	if ctx.toolchain().Bionic() {
228		// libclang_rt.builtins, libgcc and libatomic have to be last on the command line
229		if !Bool(linker.Properties.No_libcrt) {
230			deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
231			deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
232			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc_stripped")
233		} else if !Bool(linker.Properties.No_libgcc) {
234			deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
235			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
236		}
237
238		systemSharedLibs := linker.Properties.System_shared_libs
239		if systemSharedLibs == nil {
240			// Provide a default system_shared_libs if it is unspecified. Note: If an
241			// empty list [] is specified, it implies that the module declines the
242			// default system_shared_libs.
243			systemSharedLibs = []string{"libc", "libm", "libdl"}
244		}
245
246		if inList("libdl", deps.SharedLibs) {
247			// If system_shared_libs has libc but not libdl, make sure shared_libs does not
248			// have libdl to avoid loading libdl before libc.
249			if inList("libc", systemSharedLibs) {
250				if !inList("libdl", systemSharedLibs) {
251					ctx.PropertyErrorf("shared_libs",
252						"libdl must be in system_shared_libs, not shared_libs")
253				}
254				_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
255			}
256		}
257
258		if inList("libc_scudo", deps.SharedLibs) {
259			// libc_scudo is an alternate implementation of all
260			// allocation functions (malloc, free), that uses
261			// the scudo allocator instead of the default native
262			// allocator. If this library is in the list, make
263			// sure it's first so it properly overrides the
264			// allocation functions of all other shared libraries.
265			_, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs)
266			deps.SharedLibs = append([]string{"libc_scudo"}, deps.SharedLibs...)
267		}
268
269		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
270		// to avoid loading libdl before libc.
271		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
272			indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
273			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
274		}
275
276		deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
277	}
278
279	if ctx.Fuchsia() {
280		if ctx.ModuleName() != "libbioniccompat" &&
281			ctx.ModuleName() != "libcompiler_rt-extras" &&
282			ctx.ModuleName() != "libcompiler_rt" {
283			deps.StaticLibs = append(deps.StaticLibs, "libbioniccompat")
284		}
285		if ctx.ModuleName() != "libcompiler_rt" && ctx.ModuleName() != "libcompiler_rt-extras" {
286			deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt")
287		}
288
289	}
290
291	if ctx.Windows() {
292		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
293	}
294
295	return deps
296}
297
298func (linker *baseLinker) useClangLld(ctx ModuleContext) bool {
299	// Clang lld is not ready for for Darwin host executables yet.
300	// See https://lld.llvm.org/AtomLLD.html for status of lld for Mach-O.
301	if ctx.Darwin() {
302		return false
303	}
304	// http://b/110800681 - lld cannot link Android's Windows modules yet.
305	if ctx.Windows() {
306		return false
307	}
308	if linker.Properties.Use_clang_lld != nil {
309		return Bool(linker.Properties.Use_clang_lld)
310	}
311	return true
312}
313
314// Check whether the SDK version is not older than the specific one
315func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool {
316	if ctx.sdkVersion() == "current" {
317		return true
318	}
319	parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion())
320	if err != nil {
321		ctx.PropertyErrorf("sdk_version",
322			"Invalid sdk_version value (must be int or current): %q",
323			ctx.sdkVersion())
324	}
325	if parsedSdkVersion < SdkVersion {
326		return false
327	}
328	return true
329}
330
331// ModuleContext extends BaseModuleContext
332// BaseModuleContext should know if LLD is used?
333func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
334	toolchain := ctx.toolchain()
335
336	hod := "Host"
337	if ctx.Os().Class == android.Device {
338		hod = "Device"
339	}
340
341	if linker.useClangLld(ctx) {
342		flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
343		if !BoolDefault(linker.Properties.Pack_relocations, true) {
344			flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none")
345		} else if ctx.Device() {
346			// The SHT_RELR relocations is only supported by API level >= 28.
347			// Do not turn this on if older version NDK is used.
348			if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) {
349				flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
350				flags.LdFlags = append(flags.LdFlags, "-Wl,--use-android-relr-tags")
351			}
352		}
353	} else {
354		flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
355	}
356	if Bool(linker.Properties.Allow_undefined_symbols) {
357		if ctx.Darwin() {
358			// darwin defaults to treating undefined symbols as errors
359			flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup")
360		}
361	} else if !ctx.Darwin() {
362		flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
363	}
364
365	if linker.useClangLld(ctx) {
366		flags.LdFlags = append(flags.LdFlags, toolchain.ClangLldflags())
367	} else {
368		flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
369	}
370
371	if !ctx.toolchain().Bionic() && !ctx.Fuchsia() {
372		CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
373
374		flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...)
375
376		if !ctx.Windows() {
377			// Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
378			// builds
379			flags.LdFlags = append(flags.LdFlags,
380				"-ldl",
381				"-lpthread",
382				"-lm",
383			)
384			if !ctx.Darwin() {
385				flags.LdFlags = append(flags.LdFlags, "-lrt")
386			}
387		}
388	}
389
390	if ctx.Fuchsia() {
391		flags.LdFlags = append(flags.LdFlags, "-lfdio", "-lzircon")
392	}
393
394	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
395
396	flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
397
398	if ctx.Host() {
399		rpath_prefix := `\$$ORIGIN/`
400		if ctx.Darwin() {
401			rpath_prefix = "@loader_path/"
402		}
403
404		if !ctx.static() {
405			for _, rpath := range linker.dynamicProperties.RunPaths {
406				flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
407			}
408		}
409	}
410
411	if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
412		// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
413		// to older devices requires the old style hash. Fortunately, we can build with both and
414		// it'll work anywhere.
415		// This is not currently supported on MIPS architectures.
416		flags.LdFlags = append(flags.LdFlags, "-Wl,--hash-style=both")
417	}
418
419	flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
420
421	if Bool(linker.Properties.Group_static_libs) {
422		flags.GroupStaticLibs = true
423	}
424
425	// Version_script is not needed when linking stubs lib where the version
426	// script is created from the symbol map file.
427	if !linker.dynamicProperties.BuildStubs {
428		versionScript := ctx.ExpandOptionalSource(
429			linker.Properties.Version_script, "version_script")
430
431		if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil {
432			versionScript = ctx.ExpandOptionalSource(
433				linker.Properties.Target.Vendor.Version_script,
434				"target.vendor.version_script")
435		}
436
437		if versionScript.Valid() {
438			if ctx.Darwin() {
439				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
440			} else {
441				flags.LdFlags = append(flags.LdFlags,
442					"-Wl,--version-script,"+versionScript.String())
443				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
444
445				if linker.sanitize.isSanitizerEnabled(cfi) {
446					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
447					flags.LdFlags = append(flags.LdFlags,
448						"-Wl,--version-script,"+cfiExportsMap.String())
449					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
450				}
451			}
452		}
453	}
454
455	if !linker.dynamicProperties.BuildStubs {
456		symbolOrderingFile := ctx.ExpandOptionalSource(
457			linker.Properties.Symbol_ordering_file, "Symbol_ordering_file")
458		if symbolOrderingFile.Valid() {
459			flags.LdFlags = append(flags.LdFlags,
460				"-Wl,--symbol-ordering-file,"+symbolOrderingFile.String())
461			flags.LdFlagsDeps = append(flags.LdFlagsDeps, symbolOrderingFile.Path())
462		}
463	}
464
465	return flags
466}
467
468func (linker *baseLinker) link(ctx ModuleContext,
469	flags Flags, deps PathDeps, objs Objects) android.Path {
470	panic(fmt.Errorf("baseLinker doesn't know how to link"))
471}
472
473// Injecting version symbols
474// Some host modules want a version number, but we don't want to rebuild it every time.  Optionally add a step
475// after linking that injects a constant placeholder with the current version number.
476
477func init() {
478	pctx.HostBinToolVariable("symbolInjectCmd", "symbol_inject")
479}
480
481var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
482	blueprint.RuleParams{
483		Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
484			"-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile",
485		CommandDeps: []string{"$symbolInjectCmd"},
486	},
487	"buildNumberFromFile")
488
489func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
490	ctx.Build(pctx, android.BuildParams{
491		Rule:        injectVersionSymbol,
492		Description: "inject version symbol",
493		Input:       in,
494		Output:      out,
495		Args: map[string]string{
496			"buildNumberFromFile": ctx.Config().BuildNumberFromFile(),
497		},
498	})
499}
500