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	"path/filepath"
19	"strings"
20
21	"android/soong/android"
22
23	"github.com/google/blueprint"
24)
25
26var llndkImplDep = struct {
27	blueprint.DependencyTag
28}{}
29
30var (
31	llndkLibrarySuffix = ".llndk"
32	llndkHeadersSuffix = ".llndk"
33)
34
35// Creates a stub shared library based on the provided version file.
36//
37// Example:
38//
39// llndk_library {
40//     name: "libfoo",
41//     symbol_file: "libfoo.map.txt",
42//     export_include_dirs: ["include_vndk"],
43// }
44//
45type llndkLibraryProperties struct {
46	// Relative path to the symbol map.
47	// An example file can be seen here: TODO(danalbert): Make an example.
48	Symbol_file *string
49
50	// Whether to export any headers as -isystem instead of -I. Mainly for use by
51	// bionic/libc.
52	Export_headers_as_system *bool
53
54	// Which headers to process with versioner. This really only handles
55	// bionic/libc/include right now.
56	Export_preprocessed_headers []string
57
58	// Whether the system library uses symbol versions.
59	Unversioned *bool
60
61	// whether this module can be directly depended upon by libs that are installed to /vendor.
62	// When set to false, this module can only be depended on by VNDK libraries, not vendor
63	// libraries. This effectively hides this module from vendors. Default value is true.
64	Vendor_available *bool
65
66	// list of llndk headers to re-export include directories from.
67	Export_llndk_headers []string `android:"arch_variant"`
68}
69
70type llndkStubDecorator struct {
71	*libraryDecorator
72
73	Properties llndkLibraryProperties
74
75	exportHeadersTimestamp android.OptionalPath
76	versionScriptPath      android.ModuleGenPath
77}
78
79func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
80	flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
81	return addStubLibraryCompilerFlags(flags)
82}
83
84func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
85	vndkVer := ctx.Module().(*Module).VndkVersion()
86	if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
87		// For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
88		vndkVer = "current"
89	}
90	if stub.stubsVersion() != "" {
91		vndkVer = stub.stubsVersion()
92	}
93	objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
94	stub.versionScriptPath = versionScript
95	return objs
96}
97
98func (stub *llndkStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
99	headers := addSuffix(stub.Properties.Export_llndk_headers, llndkHeadersSuffix)
100	deps.HeaderLibs = append(deps.HeaderLibs, headers...)
101	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...)
102	return deps
103}
104
105func (stub *llndkStubDecorator) Name(name string) string {
106	return name + llndkLibrarySuffix
107}
108
109func (stub *llndkStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
110	stub.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(),
111		llndkLibrarySuffix)
112	return stub.libraryDecorator.linkerFlags(ctx, flags)
113}
114
115func (stub *llndkStubDecorator) processHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
116	srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
117	srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
118
119	var installPaths []android.WritablePath
120	for _, header := range srcFiles {
121		headerDir := filepath.Dir(header.String())
122		relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
123		if err != nil {
124			ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s",
125				srcDir.String(), headerDir, err)
126			continue
127		}
128
129		installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
130	}
131
132	return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
133}
134
135func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
136	objs Objects) android.Path {
137
138	if !Bool(stub.Properties.Unversioned) {
139		linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
140		flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
141		flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
142	}
143
144	if len(stub.Properties.Export_preprocessed_headers) > 0 {
145		genHeaderOutDir := android.PathForModuleGen(ctx, "include")
146
147		var timestampFiles android.Paths
148		for _, dir := range stub.Properties.Export_preprocessed_headers {
149			timestampFiles = append(timestampFiles, stub.processHeaders(ctx, dir, genHeaderOutDir))
150		}
151
152		if Bool(stub.Properties.Export_headers_as_system) {
153			stub.reexportSystemDirs(genHeaderOutDir)
154		} else {
155			stub.reexportDirs(genHeaderOutDir)
156		}
157
158		stub.reexportDeps(timestampFiles...)
159	}
160
161	if Bool(stub.Properties.Export_headers_as_system) {
162		stub.exportIncludesAsSystem(ctx)
163		stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
164	}
165
166	if stub.stubsVersion() != "" {
167		stub.reexportFlags("-D" + versioningMacroName(ctx.baseModuleName()) + "=" + stub.stubsVersion())
168	}
169
170	return stub.libraryDecorator.link(ctx, flags, deps, objs)
171}
172
173func (stub *llndkStubDecorator) nativeCoverage() bool {
174	return false
175}
176
177func NewLLndkStubLibrary() *Module {
178	module, library := NewLibrary(android.DeviceSupported)
179	library.BuildOnlyShared()
180	module.stl = nil
181	module.sanitize = nil
182	library.StripProperties.Strip.None = BoolPtr(true)
183
184	stub := &llndkStubDecorator{
185		libraryDecorator: library,
186	}
187	stub.Properties.Vendor_available = BoolPtr(true)
188	module.compiler = stub
189	module.linker = stub
190	module.installer = nil
191
192	module.AddProperties(
193		&module.Properties,
194		&stub.Properties,
195		&library.MutatedProperties,
196		&library.flagExporter.Properties)
197
198	return module
199}
200
201// llndk_library creates a stub llndk shared library based on the provided
202// version file. Example:
203//
204//    llndk_library {
205//        name: "libfoo",
206//        symbol_file: "libfoo.map.txt",
207//        export_include_dirs: ["include_vndk"],
208//    }
209func LlndkLibraryFactory() android.Module {
210	module := NewLLndkStubLibrary()
211	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
212	return module
213}
214
215type llndkHeadersDecorator struct {
216	*libraryDecorator
217}
218
219func (headers *llndkHeadersDecorator) Name(name string) string {
220	return name + llndkHeadersSuffix
221}
222
223// llndk_headers contains a set of c/c++ llndk headers files which are imported
224// by other soongs cc modules.
225func llndkHeadersFactory() android.Module {
226	module, library := NewLibrary(android.DeviceSupported)
227	library.HeaderOnly()
228	module.stl = nil
229	module.sanitize = nil
230
231	decorator := &llndkHeadersDecorator{
232		libraryDecorator: library,
233	}
234
235	module.compiler = nil
236	module.linker = decorator
237	module.installer = nil
238
239	module.AddProperties(
240		&module.Properties,
241		&library.MutatedProperties,
242		&library.flagExporter.Properties)
243
244	module.Init()
245
246	return module
247}
248
249func init() {
250	android.RegisterModuleType("llndk_library", LlndkLibraryFactory)
251	android.RegisterModuleType("llndk_headers", llndkHeadersFactory)
252}
253