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