• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 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	"android/soong/etc"
23)
24
25var (
26	llndkLibrarySuffix = ".llndk"
27)
28
29// Holds properties to describe a stub shared library based on the provided version file.
30type llndkLibraryProperties struct {
31	// Relative path to the symbol map.
32	// An example file can be seen here: TODO(danalbert): Make an example.
33	Symbol_file *string `android:"path,arch_variant"`
34
35	// Whether to export any headers as -isystem instead of -I. Mainly for use by
36	// bionic/libc.
37	Export_headers_as_system *bool
38
39	// Whether the system library uses symbol versions.
40	Unversioned *bool
41
42	// list of llndk headers to re-export include directories from.
43	Export_llndk_headers []string
44
45	// list of directories relative to the Blueprints file that willbe added to the include path
46	// (using -I) for any module that links against the LLNDK variant of this module, replacing
47	// any that were listed outside the llndk clause.
48	Override_export_include_dirs []string
49
50	// whether this module can be directly depended upon by libs that are installed
51	// to /vendor and /product.
52	// When set to true, this module can only be depended on by VNDK libraries, not
53	// vendor nor product libraries. This effectively hides this module from
54	// non-system modules. Default value is false.
55	Private *bool
56
57	// if true, make this module available to provide headers to other modules that set
58	// llndk.symbol_file.
59	Llndk_headers *bool
60
61	// moved_to_apex marks this module has having been distributed through an apex module.
62	Moved_to_apex *bool
63}
64
65func makeLlndkVars(ctx android.MakeVarsContext) {
66
67}
68
69func init() {
70	RegisterLlndkLibraryTxtType(android.InitRegistrationContext)
71	android.RegisterParallelSingletonType("movedToApexLlndkLibraries", movedToApexLlndkLibrariesFactory)
72}
73
74func movedToApexLlndkLibrariesFactory() android.Singleton {
75	return &movedToApexLlndkLibraries{}
76}
77
78type movedToApexLlndkLibraries struct {
79	movedToApexLlndkLibraries []string
80}
81
82func (s *movedToApexLlndkLibraries) GenerateBuildActions(ctx android.SingletonContext) {
83	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config.
84	movedToApexLlndkLibrariesMap := make(map[string]bool)
85	ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
86		if library, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok {
87			if library.HasLLNDKStubs && library.IsLLNDKMovedToApex {
88				movedToApexLlndkLibrariesMap[library.ImplementationModuleName] = true
89			}
90		}
91	})
92	s.movedToApexLlndkLibraries = android.SortedKeys(movedToApexLlndkLibrariesMap)
93
94	var sb strings.Builder
95	for i, l := range s.movedToApexLlndkLibraries {
96		if i > 0 {
97			sb.WriteRune(' ')
98		}
99		sb.WriteString(l)
100		sb.WriteString(".so")
101	}
102	android.WriteFileRule(ctx, MovedToApexLlndkLibrariesFile(ctx), sb.String())
103}
104
105func MovedToApexLlndkLibrariesFile(ctx android.PathContext) android.WritablePath {
106	return android.PathForIntermediates(ctx, "moved_to_apex_llndk_libraries.txt")
107}
108
109func (s *movedToApexLlndkLibraries) MakeVars(ctx android.MakeVarsContext) {
110	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(s.movedToApexLlndkLibraries, " "))
111}
112
113func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) {
114	ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
115}
116
117type llndkLibrariesTxtModule struct {
118	android.SingletonModuleBase
119
120	outputFile  android.OutputPath
121	moduleNames []string
122	fileNames   []string
123}
124
125var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{}
126
127// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
128// generated by Soong but can be referenced by other modules.
129// For example, apex_vndk can depend on these files as prebuilt.
130// Make uses LLNDK_LIBRARIES to determine which libraries to install.
131// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
132// Therefore, by removing the library here, we cause it to only be installed if libc
133// depends on it.
134func llndkLibrariesTxtFactory() android.SingletonModule {
135	m := &llndkLibrariesTxtModule{}
136	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
137	return m
138}
139
140func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
141	filename := txt.Name()
142
143	txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
144
145	installPath := android.PathForModuleInstall(ctx, "etc")
146	ctx.InstallFile(installPath, filename, txt.outputFile)
147
148	ctx.SetOutputFiles(android.Paths{txt.outputFile}, "")
149
150	etc.SetCommonPrebuiltEtcInfo(ctx, txt)
151}
152
153func getVndkFileName(info *LinkerInfo) (string, error) {
154	if info != nil {
155		if info.LibraryDecoratorInfo != nil {
156			return info.LibraryDecoratorInfo.VndkFileName, nil
157		}
158		if info.PrebuiltLibraryLinkerInfo != nil {
159			return info.PrebuiltLibraryLinkerInfo.VndkFileName, nil
160		}
161	}
162	return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", info)
163}
164
165func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
166	if txt.outputFile.String() == "" {
167		// Skip if target file path is empty
168		return
169	}
170
171	ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
172		ccInfo, ok := android.OtherModuleProvider(ctx, m, CcInfoProvider)
173		if !ok {
174			return
175		}
176		linkableInfo, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider)
177		if !ok {
178			return
179		}
180		if linkableInfo.IsLlndk && !linkableInfo.Header && !linkableInfo.IsVndkPrebuiltLibrary {
181			filename, err := getVndkFileName(ccInfo.LinkerInfo)
182			if err != nil {
183				ctx.ModuleErrorf(m, "%s", err)
184			}
185
186			if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") {
187				txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m))
188			}
189			txt.fileNames = append(txt.fileNames, filename)
190		}
191	})
192	txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames)
193	txt.fileNames = android.SortedUniqueStrings(txt.fileNames)
194
195	android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n"))
196}
197
198func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries {
199	return []android.AndroidMkEntries{{
200		Class:      "ETC",
201		OutputFile: android.OptionalPathForPath(txt.outputFile),
202		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
203			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
204				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
205			},
206		},
207	}}
208}
209
210func (txt *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) {
211	ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " "))
212}
213
214// PrebuiltEtcModule interface
215func (txt *llndkLibrariesTxtModule) BaseDir() string {
216	return "etc"
217}
218
219// PrebuiltEtcModule interface
220func (txt *llndkLibrariesTxtModule) SubDir() string {
221	return ""
222}
223
224func llndkMutator(mctx android.BottomUpMutatorContext) {
225	m, ok := mctx.Module().(*Module)
226	if !ok {
227		return
228	}
229
230	if shouldSkipLlndkMutator(mctx, m) {
231		return
232	}
233
234	lib, isLib := m.linker.(*libraryDecorator)
235	prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
236
237	if m.InVendorOrProduct() && isLib && lib.HasLLNDKStubs() {
238		m.VendorProperties.IsLLNDK = true
239	}
240	if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.HasLLNDKStubs() {
241		m.VendorProperties.IsLLNDK = true
242	}
243
244	if vndkprebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
245		if !Bool(vndkprebuilt.properties.Vndk.Enabled) {
246			m.VendorProperties.IsLLNDK = true
247		}
248	}
249}
250
251// Check for modules that mustn't be LLNDK
252func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool {
253	if !m.Enabled(mctx) {
254		return true
255	}
256	if !m.Device() {
257		return true
258	}
259	if m.Target().NativeBridge == android.NativeBridgeEnabled {
260		return true
261	}
262	return false
263}
264