• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 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	"github.com/google/blueprint/proptools"
19
20	"android/soong/android"
21	"android/soong/bazel"
22	"android/soong/bazel/cquery"
23)
24
25func init() {
26	RegisterLibraryHeadersBuildComponents(android.InitRegistrationContext)
27
28	// Register sdk member types.
29	android.RegisterSdkMemberType(headersLibrarySdkMemberType)
30
31}
32
33var headersLibrarySdkMemberType = &librarySdkMemberType{
34	SdkMemberTypeBase: android.SdkMemberTypeBase{
35		PropertyName:    "native_header_libs",
36		SupportsSdk:     true,
37		HostOsDependent: true,
38		Traits: []android.SdkMemberTrait{
39			nativeBridgeSdkTrait,
40			ramdiskImageRequiredSdkTrait,
41			recoveryImageRequiredSdkTrait,
42		},
43	},
44	prebuiltModuleType: "cc_prebuilt_library_headers",
45	noOutputFiles:      true,
46}
47
48func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) {
49	ctx.RegisterModuleType("cc_library_headers", LibraryHeaderFactory)
50	ctx.RegisterModuleType("cc_prebuilt_library_headers", prebuiltLibraryHeaderFactory)
51}
52
53type libraryHeaderBazelHandler struct {
54	module  *Module
55	library *libraryDecorator
56}
57
58var _ BazelHandler = (*libraryHeaderBazelHandler)(nil)
59
60func (handler *libraryHeaderBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
61	bazelCtx := ctx.Config().BazelContext
62	bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
63}
64
65func (h *libraryHeaderBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
66	bazelCtx := ctx.Config().BazelContext
67	ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
68	if err != nil {
69		ctx.ModuleErrorf(err.Error())
70		return
71	}
72
73	outputPaths := ccInfo.OutputFiles
74	if len(outputPaths) != 1 {
75		ctx.ModuleErrorf("expected exactly one output file for %q, but got %q", label, outputPaths)
76		return
77	}
78
79	var outputPath android.Path = android.PathForBazelOut(ctx, outputPaths[0])
80	if len(ccInfo.TidyFiles) > 0 {
81		h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
82		outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
83	}
84	h.module.outputFile = android.OptionalPathForPath(outputPath)
85
86	// HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
87	ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
88
89	h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
90
91	// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
92	// validation will fail. For now, set this to an empty list.
93	// TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
94	h.library.collectedSnapshotHeaders = android.Paths{}
95
96	h.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo)
97}
98
99// cc_library_headers contains a set of c/c++ headers which are imported by
100// other soong cc modules using the header_libs property. For best practices,
101// use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for
102// Make.
103func LibraryHeaderFactory() android.Module {
104	module, library := NewLibrary(android.HostAndDeviceSupported)
105	library.HeaderOnly()
106	module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
107	module.bazelable = true
108	module.bazelHandler = &libraryHeaderBazelHandler{module: module, library: library}
109	return module.Init()
110}
111
112// cc_prebuilt_library_headers is a prebuilt version of cc_library_headers
113func prebuiltLibraryHeaderFactory() android.Module {
114	module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "")
115	library.HeaderOnly()
116	module.bazelable = true
117	module.bazelHandler = &ccLibraryBazelHandler{module: module}
118	return module.Init()
119}
120
121type bazelCcLibraryHeadersAttributes struct {
122	Hdrs                     bazel.LabelListAttribute
123	Export_includes          bazel.StringListAttribute
124	Export_absolute_includes bazel.StringListAttribute
125	Export_system_includes   bazel.StringListAttribute
126	Deps                     bazel.LabelListAttribute
127	Implementation_deps      bazel.LabelListAttribute
128	System_dynamic_deps      bazel.LabelListAttribute
129	sdkAttributes
130}
131
132func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
133	baseAttributes := bp2BuildParseBaseProps(ctx, module)
134	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes)
135	linkerAttrs := baseAttributes.linkerAttributes
136	(&linkerAttrs.deps).Append(linkerAttrs.dynamicDeps)
137	(&linkerAttrs.deps).Append(linkerAttrs.wholeArchiveDeps)
138
139	attrs := &bazelCcLibraryHeadersAttributes{
140		Export_includes:          exportedIncludes.Includes,
141		Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
142		Export_system_includes:   exportedIncludes.SystemIncludes,
143		Deps:                     linkerAttrs.deps,
144		System_dynamic_deps:      linkerAttrs.systemDynamicDeps,
145		Hdrs:                     baseAttributes.hdrs,
146		sdkAttributes:            bp2BuildParseSdkAttributes(module),
147	}
148
149	props := bazel.BazelTargetModuleProperties{
150		Rule_class:        "cc_library_headers",
151		Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
152	}
153
154	tags := android.ApexAvailableTags(module)
155
156	ctx.CreateBazelTargetModule(props, android.CommonAttributes{
157		Name: module.Name(),
158		Tags: tags,
159	}, attrs)
160}
161
162// Append .contribution suffix to input labels
163func apiBazelTargets(ll bazel.LabelList) bazel.LabelList {
164	labels := make([]bazel.Label, 0)
165	for _, l := range ll.Includes {
166		labels = append(labels, bazel.Label{
167			Label: android.ApiContributionTargetName(l.Label),
168		})
169	}
170	return bazel.MakeLabelList(labels)
171}
172
173func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
174	// cc_api_library_headers have a 1:1 mapping to arch/no-arch
175	// For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps
176
177	// arch-agnostic includes
178	apiIncludes := getModuleLibApiIncludes(ctx, module)
179	// arch and os specific includes
180	archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module)
181	for _, arch := range allArches { // sorted iteration
182		archApiInclude := archApiIncludes[arch]
183		if !archApiInclude.isEmpty() {
184			createApiHeaderTarget(ctx, archApiInclude)
185			apiIncludes.addDep(archApiInclude.name)
186		}
187	}
188	// os==android includes
189	if !androidOsIncludes.isEmpty() {
190		createApiHeaderTarget(ctx, androidOsIncludes)
191		apiIncludes.addDep(androidOsIncludes.name)
192	}
193
194	if !apiIncludes.isEmpty() {
195		// override the name from <mod>.module-libapi.headers --> <mod>.contribution
196		apiIncludes.name = android.ApiContributionTargetName(module.Name())
197		createApiHeaderTarget(ctx, apiIncludes)
198	}
199}
200
201func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) {
202	props := bazel.BazelTargetModuleProperties{
203		Rule_class:        "cc_api_library_headers",
204		Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
205	}
206	ctx.CreateBazelTargetModule(
207		props,
208		android.CommonAttributes{
209			Name:     includes.name,
210			SkipData: proptools.BoolPtr(true),
211		},
212		&includes.attrs,
213	)
214}
215
216var (
217	allArches = []string{"arm", "arm64", "x86", "x86_64"}
218)
219
220type archApiIncludes map[string]apiIncludes
221
222func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) {
223	baseProps := bp2BuildParseBaseProps(ctx, module)
224	i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes)
225	archRet := archApiIncludes{}
226	for _, arch := range allArches {
227		includes := i.Includes.SelectValue(
228			bazel.ArchConfigurationAxis,
229			arch)
230		systemIncludes := i.SystemIncludes.SelectValue(
231			bazel.ArchConfigurationAxis,
232			arch)
233		deps := baseProps.deps.SelectValue(
234			bazel.ArchConfigurationAxis,
235			arch)
236		attrs := bazelCcLibraryHeadersAttributes{
237			Export_includes:        bazel.MakeStringListAttribute(includes),
238			Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
239		}
240		apiDeps := apiBazelTargets(deps)
241		if !apiDeps.IsEmpty() {
242			attrs.Deps = bazel.MakeLabelListAttribute(apiDeps)
243		}
244		apiIncludes := apiIncludes{
245			name: android.ApiContributionTargetName(module.Name()) + "." + arch,
246			attrs: bazelCcApiLibraryHeadersAttributes{
247				bazelCcLibraryHeadersAttributes: attrs,
248				Arch:                            proptools.StringPtr(arch),
249			},
250		}
251		archRet[arch] = apiIncludes
252	}
253
254	// apiIncludes for os == Android
255	androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid)
256	androidOsAttrs := bazelCcLibraryHeadersAttributes{
257		Export_includes: bazel.MakeStringListAttribute(
258			i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
259		),
260		Export_system_includes: bazel.MakeStringListAttribute(
261			i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
262		),
263	}
264	androidOsApiDeps := apiBazelTargets(androidOsDeps)
265	if !androidOsApiDeps.IsEmpty() {
266		androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps)
267	}
268	osRet := apiIncludes{
269		name: android.ApiContributionTargetName(module.Name()) + ".androidos",
270		attrs: bazelCcApiLibraryHeadersAttributes{
271			bazelCcLibraryHeadersAttributes: androidOsAttrs,
272		},
273	}
274	return archRet, osRet
275}
276