xref: /aosp_15_r20/build/soong/cc/object.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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	"fmt"
19	"strings"
20
21	"android/soong/android"
22
23	"github.com/google/blueprint/proptools"
24)
25
26//
27// Objects (for crt*.o)
28//
29
30func init() {
31	android.RegisterModuleType("cc_object", ObjectFactory)
32	android.RegisterSdkMemberType(ccObjectSdkMemberType)
33
34}
35
36var ccObjectSdkMemberType = &librarySdkMemberType{
37	SdkMemberTypeBase: android.SdkMemberTypeBase{
38		PropertyName: "native_objects",
39		SupportsSdk:  true,
40	},
41	prebuiltModuleType: "cc_prebuilt_object",
42}
43
44type objectLinker struct {
45	*baseLinker
46	Properties ObjectLinkerProperties
47
48	// Location of the object in the sysroot. Empty if the object is not
49	// included in the NDK.
50	ndkSysrootPath android.Path
51}
52
53type ObjectLinkerProperties struct {
54	// list of static library modules that should only provide headers for this module.
55	Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
56
57	// list of shared library modules should only provide headers for this module.
58	Shared_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
59
60	// list of modules that should only provide headers for this module.
61	Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
62
63	// list of default libraries that will provide headers for this module.  If unset, generally
64	// defaults to libc, libm, and libdl.  Set to [] to prevent using headers from the defaults.
65	System_shared_libs []string `android:"arch_variant"`
66
67	// names of other cc_object modules to link into this module using partial linking
68	Objs []string `android:"arch_variant"`
69
70	// if set, add an extra objcopy --prefix-symbols= step
71	Prefix_symbols *string
72
73	// if set, the path to a linker script to pass to ld -r when combining multiple object files.
74	Linker_script *string `android:"path,arch_variant"`
75
76	// Indicates that this module is a CRT object. CRT objects will be split
77	// into a variant per-API level between min_sdk_version and current.
78	Crt *bool
79
80	// Indicates that this module should not be included in the NDK sysroot.
81	// Only applies to CRT objects. Defaults to false.
82	Exclude_from_ndk_sysroot *bool
83}
84
85func newObject(hod android.HostOrDeviceSupported) *Module {
86	module := newBaseModule(hod, android.MultilibBoth)
87	module.sanitize = &sanitize{}
88	module.stl = &stl{}
89	return module
90}
91
92// cc_object runs the compiler without running the linker. It is rarely
93// necessary, but sometimes used to generate .s files from .c files to use as
94// input to a cc_genrule module.
95func ObjectFactory() android.Module {
96	module := newObject(android.HostAndDeviceSupported)
97	module.linker = &objectLinker{
98		baseLinker: NewBaseLinker(module.sanitize),
99	}
100	module.compiler = NewBaseCompiler()
101
102	// Clang's address-significance tables are incompatible with ld -r.
103	module.compiler.appendCflags([]string{"-fno-addrsig"})
104
105	module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType}
106
107	return module.Init()
108}
109
110func (object *objectLinker) appendLdflags(flags []string) {
111	panic(fmt.Errorf("appendLdflags on objectLinker not supported"))
112}
113
114func (object *objectLinker) linkerProps() []interface{} {
115	return []interface{}{&object.Properties}
116}
117
118func (*objectLinker) linkerInit(ctx BaseModuleContext) {}
119
120func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
121	deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs.GetOrDefault(ctx, nil)...)
122	deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
123	deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs.GetOrDefault(ctx, nil)...)
124	deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
125
126	deps.SystemSharedLibs = object.Properties.System_shared_libs
127	if deps.SystemSharedLibs == nil {
128		// Provide a default set of shared libraries if system_shared_libs is unspecified.
129		// Note: If an empty list [] is specified, it implies that the module declines the
130		// default shared libraries.
131		deps.SystemSharedLibs = append(deps.SystemSharedLibs, ctx.toolchain().DefaultSharedLibraries()...)
132	}
133	deps.LateSharedLibs = append(deps.LateSharedLibs, deps.SystemSharedLibs...)
134	return deps
135}
136
137func (object *objectLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
138	flags.Global.LdFlags = append(flags.Global.LdFlags, ctx.toolchain().ToolchainLdflags())
139
140	if lds := android.OptionalPathForModuleSrc(ctx, object.Properties.Linker_script); lds.Valid() {
141		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-T,"+lds.String())
142		flags.LdFlagsDeps = append(flags.LdFlagsDeps, lds.Path())
143	}
144	return flags
145}
146
147func (object *objectLinker) link(ctx ModuleContext,
148	flags Flags, deps PathDeps, objs Objects) android.Path {
149
150	objs = objs.Append(deps.Objs)
151
152	var output android.WritablePath
153	builderFlags := flagsToBuilderFlags(flags)
154	outputName := ctx.ModuleName()
155	if !strings.HasSuffix(outputName, objectExtension) {
156		outputName += objectExtension
157	}
158
159	// isForPlatform is terribly named and actually means isNotApex.
160	if Bool(object.Properties.Crt) &&
161		!Bool(object.Properties.Exclude_from_ndk_sysroot) && ctx.useSdk() &&
162		ctx.isSdkVariant() && ctx.isForPlatform() {
163
164		output = getVersionedLibraryInstallPath(ctx,
165			nativeApiLevelOrPanic(ctx, ctx.sdkVersion())).Join(ctx, outputName)
166		object.ndkSysrootPath = output
167	} else {
168		output = android.PathForModuleOut(ctx, outputName)
169	}
170
171	outputFile := output
172
173	if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
174		if String(object.Properties.Prefix_symbols) != "" {
175			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
176				builderFlags, output)
177		} else {
178			ctx.Build(pctx, android.BuildParams{
179				Rule:   android.Cp,
180				Input:  objs.objFiles[0],
181				Output: output,
182			})
183		}
184	} else {
185		outputAddrSig := android.PathForModuleOut(ctx, "addrsig", outputName)
186
187		if String(object.Properties.Prefix_symbols) != "" {
188			input := android.PathForModuleOut(ctx, "unprefixed", outputName)
189			transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
190				builderFlags, output)
191			output = input
192		}
193
194		transformObjsToObj(ctx, objs.objFiles, builderFlags, outputAddrSig, flags.LdFlagsDeps)
195
196		// ld -r reorders symbols and invalidates the .llvm_addrsig section, which then causes warnings
197		// if the resulting object is used with ld --icf=safe.  Strip the .llvm_addrsig section to
198		// prevent the warnings.
199		transformObjectNoAddrSig(ctx, outputAddrSig, output)
200	}
201
202	ctx.CheckbuildFile(outputFile)
203	return outputFile
204}
205
206func (object *objectLinker) linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
207	eval := module.ConfigurableEvaluator(ctx)
208	specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs.GetOrDefault(eval, nil)...)
209
210	// Must distinguish nil and [] in system_shared_libs - ensure that [] in
211	// either input list doesn't come out as nil.
212	if specifiedDeps.systemSharedLibs == nil {
213		specifiedDeps.systemSharedLibs = object.Properties.System_shared_libs
214	} else {
215		specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, object.Properties.System_shared_libs...)
216	}
217
218	return specifiedDeps
219}
220
221func (object *objectLinker) unstrippedOutputFilePath() android.Path {
222	return nil
223}
224
225func (object *objectLinker) strippedAllOutputFilePath() android.Path {
226	return nil
227}
228
229func (object *objectLinker) nativeCoverage() bool {
230	return true
231}
232
233func (object *objectLinker) coverageOutputFilePath() android.OptionalPath {
234	return android.OptionalPath{}
235}
236
237func (object *objectLinker) object() bool {
238	return true
239}
240
241func (object *objectLinker) isCrt() bool {
242	return Bool(object.Properties.Crt)
243}
244
245func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
246	object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
247	moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
248}
249