• 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 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 inList("libc_scudo", deps.SharedLibs) {
302			// libc_scudo is an alternate implementation of all
303			// allocation functions (malloc, free), that uses
304			// the scudo allocator instead of the default native
305			// allocator. If this library is in the list, make
306			// sure it's first so it properly overrides the
307			// allocation functions of all other shared libraries.
308			_, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs)
309			deps.SharedLibs = append([]string{"libc_scudo"}, deps.SharedLibs...)
310		}
311
312		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
313		// to avoid loading libdl before libc.
314		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
315			indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
316			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
317		}
318
319		deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
320	}
321
322	if ctx.Fuchsia() {
323		if ctx.ModuleName() != "libbioniccompat" &&
324			ctx.ModuleName() != "libcompiler_rt-extras" &&
325			ctx.ModuleName() != "libcompiler_rt" {
326			deps.StaticLibs = append(deps.StaticLibs, "libbioniccompat")
327		}
328		if ctx.ModuleName() != "libcompiler_rt" && ctx.ModuleName() != "libcompiler_rt-extras" {
329			deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt")
330		}
331
332	}
333
334	if ctx.Windows() {
335		deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread")
336	}
337
338	return deps
339}
340
341func (linker *baseLinker) useClangLld(ctx ModuleContext) bool {
342	// Clang lld is not ready for for Darwin host executables yet.
343	// See https://lld.llvm.org/AtomLLD.html for status of lld for Mach-O.
344	if ctx.Darwin() {
345		return false
346	}
347	if linker.Properties.Use_clang_lld != nil {
348		return Bool(linker.Properties.Use_clang_lld)
349	}
350	return true
351}
352
353// Check whether the SDK version is not older than the specific one
354func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool {
355	if ctx.sdkVersion() == "current" {
356		return true
357	}
358	parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion())
359	if err != nil {
360		ctx.PropertyErrorf("sdk_version",
361			"Invalid sdk_version value (must be int or current): %q",
362			ctx.sdkVersion())
363	}
364	if parsedSdkVersion < SdkVersion {
365		return false
366	}
367	return true
368}
369
370// ModuleContext extends BaseModuleContext
371// BaseModuleContext should know if LLD is used?
372func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
373	toolchain := ctx.toolchain()
374
375	hod := "Host"
376	if ctx.Os().Class == android.Device {
377		hod = "Device"
378	}
379
380	if linker.useClangLld(ctx) {
381		flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
382		if !BoolDefault(linker.Properties.Pack_relocations, true) {
383			flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=none")
384		} else if ctx.Device() {
385			// The SHT_RELR relocations is only supported by API level >= 28.
386			// Do not turn this on if older version NDK is used.
387			if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) {
388				flags.Global.LdFlags = append(flags.Global.LdFlags,
389					"-Wl,--pack-dyn-relocs=android+relr",
390					"-Wl,--use-android-relr-tags")
391			} else if CheckSdkVersionAtLeast(ctx, 23) {
392				flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android")
393			}
394		}
395	} else {
396		flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
397	}
398	if Bool(linker.Properties.Allow_undefined_symbols) {
399		if ctx.Darwin() {
400			// darwin defaults to treating undefined symbols as errors
401			flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-undefined,dynamic_lookup")
402		}
403	} else if !ctx.Darwin() && !ctx.Windows() {
404		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--no-undefined")
405	}
406
407	if linker.useClangLld(ctx) {
408		flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ClangLldflags())
409	} else {
410		flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ClangLdflags())
411	}
412
413	if !ctx.toolchain().Bionic() && !ctx.Fuchsia() {
414		CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
415
416		flags.Local.LdFlags = append(flags.Local.LdFlags, linker.Properties.Host_ldlibs...)
417
418		if !ctx.Windows() {
419			// Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
420			// builds
421			flags.Global.LdFlags = append(flags.Global.LdFlags,
422				"-ldl",
423				"-lpthread",
424				"-lm",
425			)
426			if !ctx.Darwin() {
427				flags.Global.LdFlags = append(flags.Global.LdFlags, "-lrt")
428			}
429		}
430	}
431
432	if ctx.Fuchsia() {
433		flags.Global.LdFlags = append(flags.Global.LdFlags, "-lfdio", "-lzircon")
434	}
435
436	if ctx.toolchain().LibclangRuntimeLibraryArch() != "" {
437		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--exclude-libs="+config.BuiltinsRuntimeLibrary(ctx.toolchain())+".a")
438	}
439
440	CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
441
442	flags.Local.LdFlags = append(flags.Local.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
443
444	if ctx.Host() && !ctx.Windows() {
445		rpath_prefix := `\$$ORIGIN/`
446		if ctx.Darwin() {
447			rpath_prefix = "@loader_path/"
448		}
449
450		if !ctx.static() {
451			for _, rpath := range linker.dynamicProperties.RunPaths {
452				flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
453			}
454		}
455	}
456
457	if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
458		// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
459		// to older devices requires the old style hash. Fortunately, we can build with both and
460		// it'll work anywhere.
461		// This is not currently supported on MIPS architectures.
462		flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
463	}
464
465	flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainClangLdflags())
466
467	if Bool(linker.Properties.Group_static_libs) {
468		flags.GroupStaticLibs = true
469	}
470
471	// Version_script is not needed when linking stubs lib where the version
472	// script is created from the symbol map file.
473	if !linker.dynamicProperties.BuildStubs {
474		versionScript := ctx.ExpandOptionalSource(
475			linker.Properties.Version_script, "version_script")
476
477		if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil {
478			versionScript = ctx.ExpandOptionalSource(
479				linker.Properties.Target.Vendor.Version_script,
480				"target.vendor.version_script")
481		}
482
483		if versionScript.Valid() {
484			if ctx.Darwin() {
485				ctx.PropertyErrorf("version_script", "Not supported on Darwin")
486			} else {
487				flags.Local.LdFlags = append(flags.Local.LdFlags,
488					"-Wl,--version-script,"+versionScript.String())
489				flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
490
491				if linker.sanitize.isSanitizerEnabled(cfi) {
492					cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
493					flags.Local.LdFlags = append(flags.Local.LdFlags,
494						"-Wl,--version-script,"+cfiExportsMap.String())
495					flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
496				}
497			}
498		}
499	}
500
501	return flags
502}
503
504func (linker *baseLinker) link(ctx ModuleContext,
505	flags Flags, deps PathDeps, objs Objects) android.Path {
506	panic(fmt.Errorf("baseLinker doesn't know how to link"))
507}
508
509func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
510	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
511
512	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
513	// either input list doesn't come out as nil.
514	if specifiedDeps.systemSharedLibs == nil {
515		specifiedDeps.systemSharedLibs = linker.Properties.System_shared_libs
516	} else {
517		specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
518	}
519
520	return specifiedDeps
521}
522
523// Injecting version symbols
524// Some host modules want a version number, but we don't want to rebuild it every time.  Optionally add a step
525// after linking that injects a constant placeholder with the current version number.
526
527func init() {
528	pctx.HostBinToolVariable("symbolInjectCmd", "symbol_inject")
529}
530
531var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
532	blueprint.RuleParams{
533		Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
534			"-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $$(cat $buildNumberFile)",
535		CommandDeps: []string{"$symbolInjectCmd"},
536	},
537	"buildNumberFile")
538
539func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
540	buildNumberFile := ctx.Config().BuildNumberFile(ctx)
541	ctx.Build(pctx, android.BuildParams{
542		Rule:        injectVersionSymbol,
543		Description: "inject version symbol",
544		Input:       in,
545		Output:      out,
546		OrderOnly:   android.Paths{buildNumberFile},
547		Args: map[string]string{
548			"buildNumberFile": buildNumberFile.String(),
549		},
550	})
551}
552
553// Rule to generate .bss symbol ordering file.
554
555var (
556	_                      = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
557	gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
558		blueprint.RuleParams{
559			Command:     "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
560			CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
561		},
562		"crossCompile")
563)
564
565func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
566	crossCompile := gccCmd(flags.toolchain, "")
567	ctx.Build(pctx, android.BuildParams{
568		Rule:        gen_sorted_bss_symbols,
569		Description: "generate bss symbol order " + symbolOrderingFile.Base(),
570		Output:      symbolOrderingFile,
571		Input:       in,
572		Args: map[string]string{
573			"crossCompile": crossCompile,
574		},
575	})
576	return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String()
577}
578