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 libclang_rt.builtins-*.a
61	No_libcrt *bool `android:"arch_variant"`
62
63	// Use clang lld instead of gnu ld.
64	Use_clang_lld *bool `android:"arch_variant"`
65
66	// -l arguments to pass to linker for host-provided shared libraries
67	Host_ldlibs []string `android:"arch_variant"`
68
69	// list of shared libraries to re-export include directories from. Entries must be
70	// present in shared_libs.
71	Export_shared_lib_headers []string `android:"arch_variant"`
72
73	// list of static libraries to re-export include directories from. Entries must be
74	// present in static_libs.
75	Export_static_lib_headers []string `android:"arch_variant"`
76
77	// list of header libraries to re-export include directories from. Entries must be
78	// present in header_libs.
79	Export_header_lib_headers []string `android:"arch_variant"`
80
81	// list of generated headers to re-export include directories from. Entries must be
82	// present in generated_headers.
83	Export_generated_headers []string `android:"arch_variant"`
84
85	// don't link in crt_begin and crt_end.  This flag should only be necessary for
86	// compiling crt or libc.
87	Nocrt *bool `android:"arch_variant"`
88
89	// group static libraries.  This can resolve missing symbols issues with interdependencies
90	// between static libraries, but it is generally better to order them correctly instead.
91	Group_static_libs *bool `android:"arch_variant"`
92
93	// list of modules that should be installed with this module.  This is similar to 'required'
94	// but '.vendor' suffix will be appended to the module names if the shared libraries have
95	// vendor variants and this module uses VNDK.
96	Runtime_libs []string `android:"arch_variant"`
97
98	Target struct {
99		Vendor struct {
100			// list of shared libs that only should be used to build the vendor
101			// variant of the C/C++ module.
102			Shared_libs []string
103
104			// list of static libs that only should be used to build the vendor
105			// variant of the C/C++ module.
106			Static_libs []string
107
108			// list of shared libs that should not be used to build the vendor variant
109			// of the C/C++ module.
110			Exclude_shared_libs []string
111
112			// list of static libs that should not be used to build the vendor variant
113			// of the C/C++ module.
114			Exclude_static_libs []string
115
116			// list of header libs that should not be used to build the vendor variant
117			// of the C/C++ module.
118			Exclude_header_libs []string
119
120			// list of runtime libs that should not be installed along with the vendor
121			// variant of the C/C++ module.
122			Exclude_runtime_libs []string
123
124			// version script for this vendor variant
125			Version_script *string `android:"arch_variant"`
126		}
127		Recovery struct {
128			// list of shared libs that only should be used to build the recovery
129			// variant of the C/C++ module.
130			Shared_libs []string
131
132			// list of static libs that only should be used to build the recovery
133			// variant of the C/C++ module.
134			Static_libs []string
135
136			// list of shared libs that should not be used to build
137			// the recovery variant of the C/C++ module.
138			Exclude_shared_libs []string
139
140			// list of static libs that should not be used to build
141			// the recovery variant of the C/C++ module.
142			Exclude_static_libs []string
143
144			// list of header libs that should not be used to build the recovery variant
145			// of the C/C++ module.
146			Exclude_header_libs []string
147		}
148		Ramdisk struct {
149			// list of static libs that only should be used to build the recovery
150			// variant of the C/C++ module.
151			Static_libs []string
152
153			// list of shared libs that should not be used to build
154			// the ramdisk variant of the C/C++ module.
155			Exclude_shared_libs []string
156
157			// list of static libs that should not be used to build
158			// the ramdisk variant of the C/C++ module.
159			Exclude_static_libs []string
160		}
161		Platform struct {
162			// list of shared libs that should be use to build the platform variant
163			// of a module that sets sdk_version.  This should rarely be necessary,
164			// in most cases the same libraries are available for the SDK and platform
165			// variants.
166			Shared_libs []string
167		}
168	}
169
170	// make android::build:GetBuildNumber() available containing the build ID.
171	Use_version_lib *bool `android:"arch_variant"`
172
173	// Generate compact dynamic relocation table, default true.
174	Pack_relocations *bool `android:"arch_variant"`
175
176	// local file name to pass to the linker as --version_script
177	Version_script *string `android:"path,arch_variant"`
178
179	// list of static libs that should not be used to build this module
180	Exclude_static_libs []string `android:"arch_variant"`
181
182	// list of shared libs that should not be used to build this module
183	Exclude_shared_libs []string `android:"arch_variant"`
184}
185
186func NewBaseLinker(sanitize *sanitize) *baseLinker {
187	return &baseLinker{sanitize: sanitize}
188}
189
190// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties
191type baseLinker struct {
192	Properties        BaseLinkerProperties
193	dynamicProperties struct {
194		RunPaths   []string `blueprint:"mutated"`
195		BuildStubs bool     `blueprint:"mutated"`
196	}
197
198	sanitize *sanitize
199}
200
201func (linker *baseLinker) appendLdflags(flags []string) {
202	linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...)
203}
204
205func (linker *baseLinker) linkerInit(ctx BaseModuleContext) {
206	if ctx.toolchain().Is64Bit() {
207		linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64")
208	} else {
209		linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib")
210	}
211}
212
213func (linker *baseLinker) linkerProps() []interface{} {
214	return []interface{}{&linker.Properties, &linker.dynamicProperties}
215}
216
217func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
218	deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
219	deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
220	deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
221	deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
222	deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...)
223
224	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...)
225	deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...)
226	deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
227	deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...)
228
229	deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Exclude_shared_libs)
230	deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Exclude_static_libs)
231	deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Exclude_static_libs)
232
233	if Bool(linker.Properties.Use_version_lib) {
234		deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
235	}
236
237	if ctx.useVndk() {
238		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
239		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
240		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
241		deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Vendor.Static_libs...)
242		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
243		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs)
244		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs)
245		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs)
246		deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
247	}
248
249	if ctx.inRecovery() {
250		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Recovery.Shared_libs...)
251		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
252		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
253		deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Recovery.Static_libs...)
254		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
255		deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Recovery.Exclude_header_libs)
256		deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Recovery.Exclude_header_libs)
257		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
258		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
259	}
260
261	if ctx.inRamdisk() {
262		deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
263		deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs)
264		deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Recovery.Static_libs...)
265		deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
266		deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs)
267		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
268	}
269
270	if !ctx.useSdk() {
271		deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Platform.Shared_libs...)
272	}
273
274	if ctx.toolchain().Bionic() {
275		// libclang_rt.builtins and libatomic have to be last on the command line
276		if !Bool(linker.Properties.No_libcrt) {
277			deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
278			deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
279		}
280
281		systemSharedLibs := linker.Properties.System_shared_libs
282		if systemSharedLibs == nil {
283			// Provide a default system_shared_libs if it is unspecified. Note: If an
284			// empty list [] is specified, it implies that the module declines the
285			// default system_shared_libs.
286			systemSharedLibs = []string{"libc", "libm", "libdl"}
287		}
288
289		if inList("libdl", deps.SharedLibs) {
290			// If system_shared_libs has libc but not libdl, make sure shared_libs does not
291			// have libdl to avoid loading libdl before libc.
292			if inList("libc", systemSharedLibs) {
293				if !inList("libdl", systemSharedLibs) {
294					ctx.PropertyErrorf("shared_libs",
295						"libdl must be in system_shared_libs, not shared_libs")
296				}
297				_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
298			}
299		}
300
301		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
302		// to avoid loading libdl before libc.
303		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
304			indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
305			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
306		}
307
308		deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
309	}
310
311	if ctx.Fuchsia() {
312		if ctx.ModuleName() != "libbioniccompat" &&
313			ctx.ModuleName() != "libcompiler_rt-extras" &&
314			ctx.ModuleName() != "libcompiler_rt" {
315			deps.StaticLibs = append(deps.StaticLibs, "libbioniccompat")
316		}
317		if ctx.ModuleName() != "libcompiler_rt" && ctx.ModuleName() != "libcompiler_rt-extras" {
318			deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt")
319		}
320
321	}
322
323	if ctx.Windows() {
324		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
325	}
326
327	return deps
328}
329
330func (linker *baseLinker) useClangLld(ctx ModuleContext) bool {
331	// Clang lld is not ready for for Darwin host executables yet.
332	// See https://lld.llvm.org/AtomLLD.html for status of lld for Mach-O.
333	if ctx.Darwin() {
334		return false
335	}
336	if linker.Properties.Use_clang_lld != nil {
337		return Bool(linker.Properties.Use_clang_lld)
338	}
339	return true
340}
341
342// Check whether the SDK version is not older than the specific one
343func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool {
344	if ctx.sdkVersion() == "current" {
345		return true
346	}
347	parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion())
348	if err != nil {
349		ctx.PropertyErrorf("sdk_version",
350			"Invalid sdk_version value (must be int or current): %q",
351			ctx.sdkVersion())
352	}
353	if parsedSdkVersion < SdkVersion {
354		return false
355	}
356	return true
357}
358
359// ModuleContext extends BaseModuleContext
360// BaseModuleContext should know if LLD is used?
361func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
362	toolchain := ctx.toolchain()
363
364	hod := "Host"
365	if ctx.Os().Class == android.Device {
366		hod = "Device"
367	}
368
369	if linker.useClangLld(ctx) {
370		flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
371		if !BoolDefault(linker.Properties.Pack_relocations, true) {
372			flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=none")
373		} else if ctx.Device() {
374			// The SHT_RELR relocations is only supported by API level >= 28.
375			// Do not turn this on if older version NDK is used.
376			if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) {
377				flags.Global.LdFlags = append(flags.Global.LdFlags,
378					"-Wl,--pack-dyn-relocs=android+relr",
379					"-Wl,--use-android-relr-tags")
380			} else if CheckSdkVersionAtLeast(ctx, 23) {
381				flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android")
382			}
383		}
384	} else {
385		flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
386	}
387	if Bool(linker.Properties.Allow_undefined_symbols) {
388		if ctx.Darwin() {
389			// darwin defaults to treating undefined symbols as errors
390			flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-undefined,dynamic_lookup")
391		}
392	} else if !ctx.Darwin() && !ctx.Windows() {
393		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--no-undefined")
394	}
395
396	if linker.useClangLld(ctx) {
397		flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ClangLldflags())
398	} else {
399		flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ClangLdflags())
400	}
401
402	if !ctx.toolchain().Bionic() && !ctx.Fuchsia() {
403		CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
404
405		flags.Local.LdFlags = append(flags.Local.LdFlags, linker.Properties.Host_ldlibs...)
406
407		if !ctx.Windows() {
408			// Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
409			// builds
410			flags.Global.LdFlags = append(flags.Global.LdFlags,
411				"-ldl",
412				"-lpthread",
413				"-lm",
414			)
415			if !ctx.Darwin() {
416				flags.Global.LdFlags = append(flags.Global.LdFlags, "-lrt")
417			}
418		}
419	}
420
421	if ctx.Fuchsia() {
422		flags.Global.LdFlags = append(flags.Global.LdFlags, "-lfdio", "-lzircon")
423	}
424
425	if ctx.toolchain().LibclangRuntimeLibraryArch() != "" {
426		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--exclude-libs="+config.BuiltinsRuntimeLibrary(ctx.toolchain())+".a")
427	}
428
429	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
430
431	flags.Local.LdFlags = append(flags.Local.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
432
433	if ctx.Host() && !ctx.Windows() {
434		rpath_prefix := `\$$ORIGIN/`
435		if ctx.Darwin() {
436			rpath_prefix = "@loader_path/"
437		}
438
439		if !ctx.static() {
440			for _, rpath := range linker.dynamicProperties.RunPaths {
441				flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
442			}
443		}
444	}
445
446	if ctx.useSdk() {
447		// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
448		// to older devices requires the old style hash. Fortunately, we can build with both and
449		// it'll work anywhere.
450		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
451	}
452
453	flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainClangLdflags())
454
455	if Bool(linker.Properties.Group_static_libs) {
456		flags.GroupStaticLibs = true
457	}
458
459	// Version_script is not needed when linking stubs lib where the version
460	// script is created from the symbol map file.
461	if !linker.dynamicProperties.BuildStubs {
462		versionScript := ctx.ExpandOptionalSource(
463			linker.Properties.Version_script, "version_script")
464
465		if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil {
466			versionScript = ctx.ExpandOptionalSource(
467				linker.Properties.Target.Vendor.Version_script,
468				"target.vendor.version_script")
469		}
470
471		if versionScript.Valid() {
472			if ctx.Darwin() {
473				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
474			} else {
475				flags.Local.LdFlags = append(flags.Local.LdFlags,
476					"-Wl,--version-script,"+versionScript.String())
477				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
478
479				if linker.sanitize.isSanitizerEnabled(cfi) {
480					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
481					flags.Local.LdFlags = append(flags.Local.LdFlags,
482						"-Wl,--version-script,"+cfiExportsMap.String())
483					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
484				}
485			}
486		}
487	}
488
489	return flags
490}
491
492func (linker *baseLinker) link(ctx ModuleContext,
493	flags Flags, deps PathDeps, objs Objects) android.Path {
494	panic(fmt.Errorf("baseLinker doesn't know how to link"))
495}
496
497func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
498	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
499
500	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
501	// either input list doesn't come out as nil.
502	if specifiedDeps.systemSharedLibs == nil {
503		specifiedDeps.systemSharedLibs = linker.Properties.System_shared_libs
504	} else {
505		specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
506	}
507
508	return specifiedDeps
509}
510
511// Injecting version symbols
512// Some host modules want a version number, but we don't want to rebuild it every time.  Optionally add a step
513// after linking that injects a constant placeholder with the current version number.
514
515func init() {
516	pctx.HostBinToolVariable("symbolInjectCmd", "symbol_inject")
517}
518
519var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
520	blueprint.RuleParams{
521		Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
522			"-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $$(cat $buildNumberFile)",
523		CommandDeps: []string{"$symbolInjectCmd"},
524	},
525	"buildNumberFile")
526
527func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
528	buildNumberFile := ctx.Config().BuildNumberFile(ctx)
529	ctx.Build(pctx, android.BuildParams{
530		Rule:        injectVersionSymbol,
531		Description: "inject version symbol",
532		Input:       in,
533		Output:      out,
534		OrderOnly:   android.Paths{buildNumberFile},
535		Args: map[string]string{
536			"buildNumberFile": buildNumberFile.String(),
537		},
538	})
539}
540
541// Rule to generate .bss symbol ordering file.
542
543var (
544	_                      = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
545	gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
546		blueprint.RuleParams{
547			Command:     "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
548			CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
549		},
550		"crossCompile")
551)
552
553func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
554	crossCompile := gccCmd(flags.toolchain, "")
555	ctx.Build(pctx, android.BuildParams{
556		Rule:        gen_sorted_bss_symbols,
557		Description: "generate bss symbol order " + symbolOrderingFile.Base(),
558		Output:      symbolOrderingFile,
559		Input:       in,
560		Args: map[string]string{
561			"crossCompile": crossCompile,
562		},
563	})
564	return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String()
565}
566