xref: /aosp_15_r20/build/soong/sysprop/sysprop_library.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright (C) 2019 The Android Open Source Project
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
15// sysprop package defines a module named sysprop_library that can implement sysprop as API
16// See https://source.android.com/devices/architecture/sysprops-apis for details
17package sysprop
18
19import (
20	"fmt"
21	"io"
22	"os"
23	"path"
24	"strings"
25	"sync"
26
27	"github.com/google/blueprint"
28	"github.com/google/blueprint/proptools"
29
30	"android/soong/android"
31	"android/soong/cc"
32	"android/soong/java"
33	"android/soong/rust"
34)
35
36type dependencyTag struct {
37	blueprint.BaseDependencyTag
38	name string
39}
40
41type syspropGenProperties struct {
42	Srcs      []string `android:"path"`
43	Scope     string
44	Name      *string
45	Check_api *string
46}
47
48type syspropJavaGenRule struct {
49	android.ModuleBase
50
51	properties syspropGenProperties
52}
53
54type syspropRustGenRule struct {
55	*rust.BaseSourceProvider
56
57	properties rustLibraryProperties
58}
59
60var _ rust.SourceProvider = (*syspropRustGenRule)(nil)
61
62var (
63	syspropJava = pctx.AndroidStaticRule("syspropJava",
64		blueprint.RuleParams{
65			Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
66				`$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` +
67				`$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
68			CommandDeps: []string{
69				"$syspropJavaCmd",
70				"$soongZipCmd",
71			},
72		}, "scope")
73	syspropRust = pctx.AndroidStaticRule("syspropRust",
74		blueprint.RuleParams{
75			Command: `rm -rf $out_dir && mkdir -p $out_dir && ` +
76				`$syspropRustCmd --scope $scope --rust-output-dir $out_dir $in`,
77			CommandDeps: []string{
78				"$syspropRustCmd",
79			},
80		}, "scope", "out_dir")
81)
82
83func init() {
84	pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
85	pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
86	pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust")
87}
88
89// syspropJavaGenRule module generates srcjar containing generated java APIs.
90// It also depends on check api rule, so api check has to pass to use sysprop_library.
91func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
92	var checkApiFileTimeStamp android.WritablePath
93
94	ctx.VisitDirectDeps(func(dep android.Module) {
95		if m, ok := dep.(*syspropLibrary); ok {
96			checkApiFileTimeStamp = m.checkApiFileTimeStamp
97		}
98	})
99
100	var genSrcjars android.Paths
101	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
102		srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
103
104		ctx.Build(pctx, android.BuildParams{
105			Rule:        syspropJava,
106			Description: "sysprop_java " + syspropFile.Rel(),
107			Output:      srcJarFile,
108			Input:       syspropFile,
109			Implicit:    checkApiFileTimeStamp,
110			Args: map[string]string{
111				"scope": g.properties.Scope,
112			},
113		})
114
115		genSrcjars = append(genSrcjars, srcJarFile)
116	}
117
118	ctx.SetOutputFiles(genSrcjars, "")
119}
120
121func (g *syspropJavaGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
122	// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
123	// the check API rule of the sysprop library.
124	ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
125}
126
127func syspropJavaGenFactory() android.Module {
128	g := &syspropJavaGenRule{}
129	g.AddProperties(&g.properties)
130	android.InitAndroidModule(g)
131	return g
132}
133
134// syspropRustGenRule module generates rust source files containing generated rust APIs.
135// It also depends on check api rule, so api check has to pass to use sysprop_library.
136func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
137	var checkApiFileTimeStamp android.WritablePath
138
139	ctx.VisitDirectDeps(func(dep android.Module) {
140		if m, ok := dep.(*syspropLibrary); ok {
141			checkApiFileTimeStamp = m.checkApiFileTimeStamp
142		}
143	})
144
145	outputDir := android.PathForModuleOut(ctx, "src")
146	libFile := outputDir.Join(ctx, "lib.rs")
147	g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, libFile)
148	libFileLines := []string{"//! Autogenerated system property accessors."}
149
150	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Sysprop_srcs) {
151		moduleName := syspropPathToRustModule(syspropFile)
152		moduleDir := outputDir.Join(ctx, moduleName)
153		modulePath := moduleDir.Join(ctx, "mod.rs")
154
155		ctx.Build(pctx, android.BuildParams{
156			Rule:        syspropRust,
157			Description: "sysprop_rust " + syspropFile.Rel(),
158			Output:      modulePath,
159			Input:       syspropFile,
160			Implicit:    checkApiFileTimeStamp,
161			Args: map[string]string{
162				"scope":   g.properties.Scope,
163				"out_dir": moduleDir.String(),
164			},
165		})
166
167		g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, modulePath)
168		libFileLines = append(libFileLines, fmt.Sprintf("pub mod %s;", moduleName))
169	}
170
171	libFileSource := strings.Join(libFileLines, "\n")
172	android.WriteFileRule(ctx, libFile, libFileSource)
173
174	return libFile
175}
176
177func (g *syspropRustGenRule) SourceProviderProps() []interface{} {
178	return append(g.BaseSourceProvider.SourceProviderProps(), &g.Properties)
179}
180
181// syspropPathToRustModule takes a path to a .sysprop file and returns the name to use for the
182// corresponding Rust module.
183func syspropPathToRustModule(syspropFilename android.Path) string {
184	filenameBase := strings.TrimSuffix(syspropFilename.Base(), ".sysprop")
185	return strings.ToLower(filenameBase)
186}
187
188func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
189	// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
190	// the check API rule of the sysprop library.
191	ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
192}
193
194func syspropRustGenFactory() android.Module {
195	g := &syspropRustGenRule{
196		BaseSourceProvider: rust.NewSourceProvider(),
197	}
198	sourceProvider := rust.NewSourceProviderModule(android.DeviceSupported, g, false, false)
199	sourceProvider.AddProperties(&g.properties)
200	return sourceProvider.Init()
201}
202
203type syspropLibrary struct {
204	android.ModuleBase
205	android.ApexModuleBase
206
207	properties syspropLibraryProperties
208
209	checkApiFileTimeStamp android.WritablePath
210	latestApiFile         android.OptionalPath
211	currentApiFile        android.OptionalPath
212	dumpedApiFile         android.WritablePath
213}
214
215type syspropLibraryProperties struct {
216	// Determine who owns this sysprop library. Possible values are
217	// "Platform", "Vendor", or "Odm"
218	Property_owner string
219
220	// list of package names that will be documented and publicized as API
221	Api_packages []string
222
223	// If set to true, allow this module to be dexed and installed on devices.
224	Installable *bool
225
226	// Make this module available when building for ramdisk
227	Ramdisk_available *bool
228
229	// Make this module available when building for recovery
230	Recovery_available *bool
231
232	// Make this module available when building for vendor
233	Vendor_available *bool
234
235	// Make this module available when building for product
236	Product_available *bool
237
238	// list of .sysprop files which defines the properties.
239	Srcs []string `android:"path"`
240
241	// If set to true, build a variant of the module for the host.  Defaults to false.
242	Host_supported *bool
243
244	Cpp struct {
245		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
246		// Forwarded to cc_library.min_sdk_version
247		Min_sdk_version *string
248
249		// C compiler flags used to build library
250		Cflags []string
251
252		// Linker flags used to build binary
253		Ldflags []string
254	}
255
256	Java struct {
257		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
258		// Forwarded to java_library.min_sdk_version
259		Min_sdk_version *string
260	}
261
262	Rust struct {
263		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
264		// Forwarded to rust_library.min_sdk_version
265		Min_sdk_version *string
266	}
267}
268
269var (
270	pctx         = android.NewPackageContext("android/soong/sysprop")
271	syspropCcTag = dependencyTag{name: "syspropCc"}
272
273	syspropLibrariesKey  = android.NewOnceKey("syspropLibraries")
274	syspropLibrariesLock sync.Mutex
275)
276
277// List of sysprop_library used by property_contexts to perform type check.
278func syspropLibraries(config android.Config) *[]string {
279	return config.Once(syspropLibrariesKey, func() interface{} {
280		return &[]string{}
281	}).(*[]string)
282}
283
284func SyspropLibraries(config android.Config) []string {
285	return append([]string{}, *syspropLibraries(config)...)
286}
287
288func init() {
289	registerSyspropBuildComponents(android.InitRegistrationContext)
290}
291
292func registerSyspropBuildComponents(ctx android.RegistrationContext) {
293	ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
294}
295
296func (m *syspropLibrary) Name() string {
297	return m.BaseModuleName() + "_sysprop_library"
298}
299
300func (m *syspropLibrary) Owner() string {
301	return m.properties.Property_owner
302}
303
304func (m *syspropLibrary) CcImplementationModuleName() string {
305	return "lib" + m.BaseModuleName()
306}
307
308func (m *syspropLibrary) javaPublicStubName() string {
309	return m.BaseModuleName() + "_public"
310}
311
312func (m *syspropLibrary) javaGenModuleName() string {
313	return m.BaseModuleName() + "_java_gen"
314}
315
316func (m *syspropLibrary) javaGenPublicStubName() string {
317	return m.BaseModuleName() + "_java_gen_public"
318}
319
320func (m *syspropLibrary) rustGenStubName() string {
321	return "lib" + m.rustCrateName() + "_rust"
322}
323
324func (m *syspropLibrary) rustCrateName() string {
325	moduleName := strings.ToLower(m.BaseModuleName())
326	moduleName = strings.ReplaceAll(moduleName, "-", "_")
327	moduleName = strings.ReplaceAll(moduleName, ".", "_")
328	return moduleName
329}
330
331func (m *syspropLibrary) BaseModuleName() string {
332	return m.ModuleBase.Name()
333}
334
335func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath {
336	return m.currentApiFile
337}
338
339// GenerateAndroidBuildActions of sysprop_library handles API dump and API check.
340// generated java_library will depend on these API files.
341func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
342	baseModuleName := m.BaseModuleName()
343	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
344	for _, syspropFile := range srcs {
345		if syspropFile.Ext() != ".sysprop" {
346			ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
347		}
348	}
349	android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
350
351	if ctx.Failed() {
352		return
353	}
354
355	apiDirectoryPath := path.Join(ctx.ModuleDir(), "api")
356	currentApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-current.txt")
357	latestApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-latest.txt")
358	m.currentApiFile = android.ExistentPathForSource(ctx, currentApiFilePath)
359	m.latestApiFile = android.ExistentPathForSource(ctx, latestApiFilePath)
360
361	// dump API rule
362	rule := android.NewRuleBuilder(pctx, ctx)
363	m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt")
364	rule.Command().
365		BuiltTool("sysprop_api_dump").
366		Output(m.dumpedApiFile).
367		Inputs(srcs)
368	rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump")
369
370	// check API rule
371	rule = android.NewRuleBuilder(pctx, ctx)
372
373	// We allow that the API txt files don't exist, when the sysprop_library only contains internal
374	// properties. But we have to feed current api file and latest api file to the rule builder.
375	// Currently we can't get android.Path representing the null device, so we add any existing API
376	// txt files to implicits, and then directly feed string paths, rather than calling Input(Path)
377	// method.
378	var apiFileList android.Paths
379	currentApiArgument := os.DevNull
380	if m.currentApiFile.Valid() {
381		apiFileList = append(apiFileList, m.currentApiFile.Path())
382		currentApiArgument = m.currentApiFile.String()
383	}
384
385	latestApiArgument := os.DevNull
386	if m.latestApiFile.Valid() {
387		apiFileList = append(apiFileList, m.latestApiFile.Path())
388		latestApiArgument = m.latestApiFile.String()
389	}
390
391	// 1. compares current.txt to api-dump.txt
392	// current.txt should be identical to api-dump.txt.
393	msg := fmt.Sprintf(`\n******************************\n`+
394		`API of sysprop_library %s doesn't match with current.txt\n`+
395		`Please update current.txt by:\n`+
396		`m %s-dump-api && mkdir -p %q && rm -rf %q && cp -f %q %q\n`+
397		`******************************\n`, baseModuleName, baseModuleName,
398		apiDirectoryPath, currentApiFilePath, m.dumpedApiFile.String(), currentApiFilePath)
399
400	rule.Command().
401		Text("( cmp").Flag("-s").
402		Input(m.dumpedApiFile).
403		Text(currentApiArgument).
404		Text("|| ( echo").Flag("-e").
405		Flag(`"` + msg + `"`).
406		Text("; exit 38) )")
407
408	// 2. compares current.txt to latest.txt (frozen API)
409	// current.txt should be compatible with latest.txt
410	msg = fmt.Sprintf(`\n******************************\n`+
411		`API of sysprop_library %s doesn't match with latest version\n`+
412		`Please fix the breakage and rebuild.\n`+
413		`******************************\n`, baseModuleName)
414
415	rule.Command().
416		Text("( ").
417		BuiltTool("sysprop_api_checker").
418		Text(latestApiArgument).
419		Text(currentApiArgument).
420		Text(" || ( echo").Flag("-e").
421		Flag(`"` + msg + `"`).
422		Text("; exit 38) )").
423		Implicits(apiFileList)
424
425	m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp")
426
427	rule.Command().
428		Text("touch").
429		Output(m.checkApiFileTimeStamp)
430
431	rule.Build(baseModuleName+"_check_api", baseModuleName+" check api")
432}
433
434func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
435	return android.AndroidMkData{
436		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
437			// sysprop_library module itself is defined as a FAKE module to perform API check.
438			// Actual implementation libraries are created on LoadHookMutator
439			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # sysprop.syspropLibrary")
440			fmt.Fprintln(w, "LOCAL_MODULE :=", m.Name())
441			fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
442			fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
443			// AconfigUpdateAndroidMkData may have added elements to Extra.  Process them here.
444			for _, extra := range data.Extra {
445				extra(w, nil)
446			}
447			fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
448			fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
449			fmt.Fprintf(w, "\ttouch $@\n\n")
450			fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name)
451
452			// dump API rule
453			fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String())
454
455			// check API rule
456			fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
457		}}
458}
459
460var _ android.ApexModule = (*syspropLibrary)(nil)
461
462// Implements android.ApexModule
463func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
464	sdkVersion android.ApiLevel) error {
465	return fmt.Errorf("sysprop_library is not supposed to be part of apex modules")
466}
467
468// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
469// Both Java and C++ modules can link against sysprop_library, and API stability check
470// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
471// is performed. Note that the generated C++ module has its name prefixed with
472// `lib`, and it is this module that should be depended on from other C++
473// modules; i.e., if the sysprop_library module is named `foo`, C++ modules
474// should depend on `libfoo`.
475func syspropLibraryFactory() android.Module {
476	m := &syspropLibrary{}
477
478	m.AddProperties(
479		&m.properties,
480	)
481	android.InitAndroidModule(m)
482	android.InitApexModule(m)
483	android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
484	return m
485}
486
487type ccLibraryProperties struct {
488	Name             *string
489	Srcs             []string
490	Soc_specific     *bool
491	Device_specific  *bool
492	Product_specific *bool
493	Sysprop          struct {
494		Platform *bool
495	}
496	Target struct {
497		Android struct {
498			Header_libs []string
499			Shared_libs []string
500		}
501		Host struct {
502			Static_libs []string
503		}
504	}
505	Required           []string
506	Recovery           *bool
507	Recovery_available *bool
508	Vendor_available   *bool
509	Product_available  *bool
510	Ramdisk_available  *bool
511	Host_supported     *bool
512	Apex_available     []string
513	Min_sdk_version    *string
514	Cflags             []string
515	Ldflags            []string
516}
517
518type javaLibraryProperties struct {
519	Name              *string
520	Srcs              []string
521	Soc_specific      *bool
522	Device_specific   *bool
523	Product_specific  *bool
524	Required          []string
525	Sdk_version       *string
526	Installable       *bool
527	Libs              []string
528	Stem              *string
529	SyspropPublicStub string
530	Apex_available    []string
531	Min_sdk_version   *string
532}
533
534type rustLibraryProperties struct {
535	Name              *string
536	Sysprop_srcs      []string `android:"path"`
537	Scope             string
538	Check_api         *string
539	Srcs              []string
540	Installable       *bool
541	Crate_name        string
542	Rustlibs          []string
543	Vendor_available  *bool
544	Product_available *bool
545	Apex_available    []string
546	Min_sdk_version   *string
547}
548
549func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
550	if len(m.properties.Srcs) == 0 {
551		ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
552	}
553
554	// ctx's Platform or Specific functions represent where this sysprop_library installed.
555	installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
556	installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
557	installedInProduct := ctx.ProductSpecific()
558	isOwnerPlatform := false
559	var javaSyspropStub string
560
561	// javaSyspropStub contains stub libraries used by generated APIs, instead of framework stub.
562	// This is to make sysprop_library link against core_current.
563	if installedInVendorOrOdm {
564		javaSyspropStub = "sysprop-library-stub-vendor"
565	} else if installedInProduct {
566		javaSyspropStub = "sysprop-library-stub-product"
567	} else {
568		javaSyspropStub = "sysprop-library-stub-platform"
569	}
570
571	switch m.Owner() {
572	case "Platform":
573		// Every partition can access platform-defined properties
574		isOwnerPlatform = true
575	case "Vendor":
576		// System can't access vendor's properties
577		if installedInSystem {
578			ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
579				"System can't access sysprop_library owned by Vendor")
580		}
581	case "Odm":
582		// Only vendor can access Odm-defined properties
583		if !installedInVendorOrOdm {
584			ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
585				"Odm-defined properties should be accessed only in Vendor or Odm")
586		}
587	default:
588		ctx.PropertyErrorf("property_owner",
589			"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
590	}
591
592	// Generate a C++ implementation library.
593	// cc_library can receive *.sysprop files as their srcs, generating sources itself.
594	ccProps := ccLibraryProperties{}
595	ccProps.Name = proptools.StringPtr(m.CcImplementationModuleName())
596	ccProps.Srcs = m.properties.Srcs
597	ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific())
598	ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
599	ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
600	ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
601	ccProps.Target.Android.Header_libs = []string{"libbase_headers"}
602	ccProps.Target.Android.Shared_libs = []string{"liblog"}
603	ccProps.Target.Host.Static_libs = []string{"libbase", "liblog"}
604	ccProps.Recovery_available = m.properties.Recovery_available
605	ccProps.Vendor_available = m.properties.Vendor_available
606	ccProps.Product_available = m.properties.Product_available
607	ccProps.Ramdisk_available = m.properties.Ramdisk_available
608	ccProps.Host_supported = m.properties.Host_supported
609	ccProps.Apex_available = m.ApexProperties.Apex_available
610	ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
611	ccProps.Cflags = m.properties.Cpp.Cflags
612	ccProps.Ldflags = m.properties.Cpp.Ldflags
613	ctx.CreateModule(cc.LibraryFactory, &ccProps)
614
615	scope := "internal"
616
617	// We need to only use public version, if the partition where sysprop_library will be installed
618	// is different from owner.
619	if ctx.ProductSpecific() {
620		// Currently product partition can't own any sysprop_library. So product always uses public.
621		scope = "public"
622	} else if isOwnerPlatform && installedInVendorOrOdm {
623		// Vendor or Odm should use public version of Platform's sysprop_library.
624		scope = "public"
625	}
626
627	// Generate a Java implementation library.
628	// Contrast to C++, syspropJavaGenRule module will generate srcjar and the srcjar will be fed
629	// to Java implementation library.
630	ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
631		Srcs:      m.properties.Srcs,
632		Scope:     scope,
633		Name:      proptools.StringPtr(m.javaGenModuleName()),
634		Check_api: proptools.StringPtr(ctx.ModuleName()),
635	})
636
637	// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
638	// and allow any modules (even from different partition) to link against the sysprop_library.
639	// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
640	var publicStub string
641	if isOwnerPlatform && installedInSystem {
642		publicStub = m.javaPublicStubName()
643	}
644
645	ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
646		Name:              proptools.StringPtr(m.BaseModuleName()),
647		Srcs:              []string{":" + m.javaGenModuleName()},
648		Soc_specific:      proptools.BoolPtr(ctx.SocSpecific()),
649		Device_specific:   proptools.BoolPtr(ctx.DeviceSpecific()),
650		Product_specific:  proptools.BoolPtr(ctx.ProductSpecific()),
651		Installable:       m.properties.Installable,
652		Sdk_version:       proptools.StringPtr("core_current"),
653		Libs:              []string{javaSyspropStub},
654		SyspropPublicStub: publicStub,
655		Apex_available:    m.ApexProperties.Apex_available,
656		Min_sdk_version:   m.properties.Java.Min_sdk_version,
657	})
658
659	if publicStub != "" {
660		ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
661			Srcs:      m.properties.Srcs,
662			Scope:     "public",
663			Name:      proptools.StringPtr(m.javaGenPublicStubName()),
664			Check_api: proptools.StringPtr(ctx.ModuleName()),
665		})
666
667		ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
668			Name:        proptools.StringPtr(publicStub),
669			Srcs:        []string{":" + m.javaGenPublicStubName()},
670			Installable: proptools.BoolPtr(false),
671			Sdk_version: proptools.StringPtr("core_current"),
672			Libs:        []string{javaSyspropStub},
673			Stem:        proptools.StringPtr(m.BaseModuleName()),
674		})
675	}
676
677	// Generate a Rust implementation library.
678	rustProps := rustLibraryProperties{
679		Name:         proptools.StringPtr(m.rustGenStubName()),
680		Sysprop_srcs: m.properties.Srcs,
681		Scope:        scope,
682		Check_api:    proptools.StringPtr(ctx.ModuleName()),
683		Installable:  proptools.BoolPtr(false),
684		Crate_name:   m.rustCrateName(),
685		Rustlibs: []string{
686			"liblog_rust",
687			"librustutils",
688		},
689		Vendor_available:  m.properties.Vendor_available,
690		Product_available: m.properties.Product_available,
691		Apex_available:    m.ApexProperties.Apex_available,
692		Min_sdk_version:   proptools.StringPtr("29"),
693	}
694	ctx.CreateModule(syspropRustGenFactory, &rustProps)
695
696	// syspropLibraries will be used by property_contexts to check types.
697	// Record absolute paths of sysprop_library to prevent soong_namespace problem.
698	if m.ExportedToMake() {
699		syspropLibrariesLock.Lock()
700		defer syspropLibrariesLock.Unlock()
701
702		libraries := syspropLibraries(ctx.Config())
703		*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
704	}
705}
706