1// Copyright 2021 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. 14package cc 15 16import ( 17 "fmt" 18 "path/filepath" 19 "strings" 20 21 "android/soong/android" 22 "android/soong/bazel" 23 "android/soong/cc/config" 24 25 "github.com/google/blueprint" 26 27 "github.com/google/blueprint/proptools" 28) 29 30const ( 31 cSrcPartition = "c" 32 asSrcPartition = "as" 33 asmSrcPartition = "asm" 34 lSrcPartition = "l" 35 llSrcPartition = "ll" 36 cppSrcPartition = "cpp" 37 protoSrcPartition = "proto" 38 aidlSrcPartition = "aidl" 39 syspropSrcPartition = "sysprop" 40 41 stubsSuffix = "_stub_libs_current" 42) 43 44// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- 45// properties which apply to either the shared or static version of a cc_library module. 46type staticOrSharedAttributes struct { 47 Srcs bazel.LabelListAttribute 48 Srcs_c bazel.LabelListAttribute 49 Srcs_as bazel.LabelListAttribute 50 Srcs_aidl bazel.LabelListAttribute 51 Hdrs bazel.LabelListAttribute 52 Copts bazel.StringListAttribute 53 54 Deps bazel.LabelListAttribute 55 Implementation_deps bazel.LabelListAttribute 56 Dynamic_deps bazel.LabelListAttribute 57 Implementation_dynamic_deps bazel.LabelListAttribute 58 Whole_archive_deps bazel.LabelListAttribute 59 Implementation_whole_archive_deps bazel.LabelListAttribute 60 Runtime_deps bazel.LabelListAttribute 61 62 System_dynamic_deps bazel.LabelListAttribute 63 64 Enabled bazel.BoolAttribute 65 66 Native_coverage *bool 67 68 Apex_available []string 69 70 sdkAttributes 71 72 tidyAttributes 73} 74 75type tidyAttributes struct { 76 Tidy *string 77 Tidy_flags []string 78 Tidy_checks []string 79 Tidy_checks_as_errors []string 80 Tidy_disabled_srcs bazel.LabelListAttribute 81 Tidy_timeout_srcs bazel.LabelListAttribute 82} 83 84func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) { 85 for _, f := range m.features { 86 if tidy, ok := f.(*tidyFeature); ok { 87 var tidyAttr *string 88 if tidy.Properties.Tidy != nil { 89 if *tidy.Properties.Tidy { 90 tidyAttr = proptools.StringPtr("local") 91 } else { 92 tidyAttr = proptools.StringPtr("never") 93 } 94 } 95 moduleAttrs.Tidy = tidyAttr 96 moduleAttrs.Tidy_flags = tidy.Properties.Tidy_flags 97 moduleAttrs.Tidy_checks = tidy.Properties.Tidy_checks 98 moduleAttrs.Tidy_checks_as_errors = tidy.Properties.Tidy_checks_as_errors 99 } 100 101 } 102 archVariantProps := m.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) 103 for axis, configToProps := range archVariantProps { 104 for cfg, _props := range configToProps { 105 if archProps, ok := _props.(*BaseCompilerProperties); ok { 106 archDisabledSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_disabled_srcs) 107 moduleAttrs.Tidy_disabled_srcs.SetSelectValue(axis, cfg, archDisabledSrcs) 108 archTimeoutSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_timeout_srcs) 109 moduleAttrs.Tidy_timeout_srcs.SetSelectValue(axis, cfg, archTimeoutSrcs) 110 } 111 } 112 } 113} 114 115// groupSrcsByExtension partitions `srcs` into groups based on file extension. 116func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { 117 // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl 118 // macro. 119 addSuffixForFilegroup := func(suffix string) bazel.LabelMapper { 120 return func(otherModuleCtx bazel.OtherModuleContext, label bazel.Label) (string, bool) { 121 122 m, exists := otherModuleCtx.ModuleFromName(label.OriginalModuleName) 123 labelStr := label.Label 124 if !exists || !android.IsFilegroup(otherModuleCtx, m) { 125 return labelStr, false 126 } 127 // If the filegroup is already converted to aidl_library or proto_library, 128 // skip creating _c_srcs, _as_srcs, _cpp_srcs filegroups 129 fg, _ := m.(android.FileGroupAsLibrary) 130 if fg.ShouldConvertToAidlLibrary(ctx) || fg.ShouldConvertToProtoLibrary(ctx) { 131 return labelStr, false 132 } 133 return labelStr + suffix, true 134 } 135 } 136 137 // TODO(b/190006308): Handle language detection of sources in a Bazel rule. 138 labels := bazel.LabelPartitions{ 139 protoSrcPartition: android.ProtoSrcLabelPartition, 140 cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, 141 asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, 142 asmSrcPartition: bazel.LabelPartition{Extensions: []string{".asm"}}, 143 aidlSrcPartition: android.AidlSrcLabelPartition, 144 // TODO(http://b/231968910): If there is ever a filegroup target that 145 // contains .l or .ll files we will need to find a way to add a 146 // LabelMapper for these that identifies these filegroups and 147 // converts them appropriately 148 lSrcPartition: bazel.LabelPartition{Extensions: []string{".l"}}, 149 llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}}, 150 // C++ is the "catch-all" group, and comprises generated sources because we don't 151 // know the language of these sources until the genrule is executed. 152 cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, 153 syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}}, 154 } 155 156 return bazel.PartitionLabelListAttribute(ctx, &srcs, labels) 157} 158 159// bp2BuildParseLibProps returns the attributes for a variant of a cc_library. 160func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes { 161 lib, ok := module.compiler.(*libraryDecorator) 162 if !ok { 163 return staticOrSharedAttributes{} 164 } 165 return bp2buildParseStaticOrSharedProps(ctx, module, lib, isStatic) 166} 167 168// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library. 169func bp2BuildParseSharedProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes { 170 return bp2BuildParseLibProps(ctx, module, false) 171} 172 173// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library. 174func bp2BuildParseStaticProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes { 175 return bp2BuildParseLibProps(ctx, module, true) 176} 177 178type depsPartition struct { 179 export bazel.LabelList 180 implementation bazel.LabelList 181} 182 183type bazelLabelForDepsFn func(android.BazelConversionPathContext, []string) bazel.LabelList 184 185func maybePartitionExportedAndImplementationsDeps(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition { 186 if !exportsDeps { 187 return depsPartition{ 188 implementation: fn(ctx, allDeps), 189 } 190 } 191 192 implementation, export := android.FilterList(allDeps, exportedDeps) 193 194 return depsPartition{ 195 export: fn(ctx, export), 196 implementation: fn(ctx, implementation), 197 } 198} 199 200type bazelLabelForDepsExcludesFn func(android.BazelConversionPathContext, []string, []string) bazel.LabelList 201 202func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition { 203 if !exportsDeps { 204 return depsPartition{ 205 implementation: fn(ctx, allDeps, excludes), 206 } 207 } 208 implementation, export := android.FilterList(allDeps, exportedDeps) 209 210 return depsPartition{ 211 export: fn(ctx, export, excludes), 212 implementation: fn(ctx, implementation, excludes), 213 } 214} 215 216func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) { 217 for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) { 218 for cfg, props := range configToProps { 219 parseFunc(axis, cfg, props) 220 } 221 } 222} 223 224// Parses properties common to static and shared libraries. Also used for prebuilt libraries. 225func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes { 226 attrs := staticOrSharedAttributes{} 227 228 setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) { 229 attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag)) 230 attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs)) 231 attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs)) 232 233 staticDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps) 234 attrs.Deps.SetSelectValue(axis, config, staticDeps.export) 235 attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation) 236 237 sharedDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps) 238 attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export) 239 attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation) 240 241 attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs)) 242 attrs.Enabled.SetSelectValue(axis, config, props.Enabled) 243 } 244 // system_dynamic_deps distinguishes between nil/empty list behavior: 245 // nil -> use default values 246 // empty list -> no values specified 247 attrs.System_dynamic_deps.ForceSpecifyEmptyList = true 248 249 var apexAvailable []string 250 if isStatic { 251 apexAvailable = lib.StaticProperties.Static.Apex_available 252 bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 253 if staticOrSharedProps, ok := props.(*StaticProperties); ok { 254 setAttrs(axis, config, staticOrSharedProps.Static) 255 } 256 }) 257 } else { 258 apexAvailable = lib.SharedProperties.Shared.Apex_available 259 bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 260 if staticOrSharedProps, ok := props.(*SharedProperties); ok { 261 setAttrs(axis, config, staticOrSharedProps.Shared) 262 } 263 }) 264 } 265 266 partitionedSrcs := groupSrcsByExtension(ctx, attrs.Srcs) 267 attrs.Srcs = partitionedSrcs[cppSrcPartition] 268 attrs.Srcs_c = partitionedSrcs[cSrcPartition] 269 attrs.Srcs_as = partitionedSrcs[asSrcPartition] 270 271 attrs.Apex_available = android.ConvertApexAvailableToTags(apexAvailable) 272 273 if !partitionedSrcs[protoSrcPartition].IsEmpty() { 274 // TODO(b/208815215): determine whether this is used and add support if necessary 275 ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported") 276 } 277 278 return attrs 279} 280 281// Convenience struct to hold all attributes parsed from prebuilt properties. 282type prebuiltAttributes struct { 283 Src bazel.LabelAttribute 284 Enabled bazel.BoolAttribute 285} 286 287func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) { 288 srcFileError := func() { 289 ctx.ModuleErrorf("parseSrc: Expected at most one source file for %s %s\n", axis, config) 290 } 291 if len(srcs) > 1 { 292 srcFileError() 293 return 294 } else if len(srcs) == 0 { 295 return 296 } 297 if srcLabelAttribute.SelectValue(axis, config) != nil { 298 srcFileError() 299 return 300 } 301 srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, srcs[0])) 302} 303 304// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package 305func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) prebuiltAttributes { 306 307 var srcLabelAttribute bazel.LabelAttribute 308 bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 309 if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok { 310 parseSrc(ctx, &srcLabelAttribute, axis, config, prebuiltLinkerProperties.Srcs) 311 } 312 }) 313 314 var enabledLabelAttribute bazel.BoolAttribute 315 parseAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) { 316 if props.Enabled != nil { 317 enabledLabelAttribute.SetSelectValue(axis, config, props.Enabled) 318 } 319 parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs) 320 } 321 322 if isStatic { 323 bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 324 if staticProperties, ok := props.(*StaticProperties); ok { 325 parseAttrs(axis, config, staticProperties.Static) 326 } 327 }) 328 } else { 329 bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 330 if sharedProperties, ok := props.(*SharedProperties); ok { 331 parseAttrs(axis, config, sharedProperties.Shared) 332 } 333 }) 334 } 335 336 return prebuiltAttributes{ 337 Src: srcLabelAttribute, 338 Enabled: enabledLabelAttribute, 339 } 340} 341 342func bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes { 343 var srcLabelAttribute bazel.LabelAttribute 344 bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 345 if props, ok := props.(*prebuiltLinkerProperties); ok { 346 parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs) 347 } 348 }) 349 350 return prebuiltAttributes{ 351 Src: srcLabelAttribute, 352 } 353} 354 355func bp2BuildParsePrebuiltObjectProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes { 356 var srcLabelAttribute bazel.LabelAttribute 357 bp2BuildPropParseHelper(ctx, module, &prebuiltObjectProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 358 if props, ok := props.(*prebuiltObjectProperties); ok { 359 parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs) 360 } 361 }) 362 363 return prebuiltAttributes{ 364 Src: srcLabelAttribute, 365 } 366} 367 368type baseAttributes struct { 369 compilerAttributes 370 linkerAttributes 371 372 // A combination of compilerAttributes.features and linkerAttributes.features, as well as sanitizer features 373 features bazel.StringListAttribute 374 protoDependency *bazel.LabelAttribute 375 aidlDependency *bazel.LabelAttribute 376 Native_coverage *bool 377} 378 379// Convenience struct to hold all attributes parsed from compiler properties. 380type compilerAttributes struct { 381 // Options for all languages 382 copts bazel.StringListAttribute 383 // Assembly options and sources 384 asFlags bazel.StringListAttribute 385 asSrcs bazel.LabelListAttribute 386 asmSrcs bazel.LabelListAttribute 387 // C options and sources 388 conlyFlags bazel.StringListAttribute 389 cSrcs bazel.LabelListAttribute 390 // C++ options and sources 391 cppFlags bazel.StringListAttribute 392 srcs bazel.LabelListAttribute 393 394 // Lex sources and options 395 lSrcs bazel.LabelListAttribute 396 llSrcs bazel.LabelListAttribute 397 lexopts bazel.StringListAttribute 398 399 // Sysprop sources 400 syspropSrcs bazel.LabelListAttribute 401 402 hdrs bazel.LabelListAttribute 403 404 rtti bazel.BoolAttribute 405 406 // Not affected by arch variants 407 stl *string 408 cStd *string 409 cppStd *string 410 411 localIncludes bazel.StringListAttribute 412 absoluteIncludes bazel.StringListAttribute 413 414 includes BazelIncludes 415 416 protoSrcs bazel.LabelListAttribute 417 aidlSrcs bazel.LabelListAttribute 418 419 stubsSymbolFile *string 420 stubsVersions bazel.StringListAttribute 421 422 features bazel.StringListAttribute 423 424 suffix bazel.StringAttribute 425 426 fdoProfile bazel.LabelAttribute 427} 428 429type filterOutFn func(string) bool 430 431func filterOutStdFlag(flag string) bool { 432 return strings.HasPrefix(flag, "-std=") 433} 434 435func filterOutClangUnknownCflags(flag string) bool { 436 for _, f := range config.ClangUnknownCflags { 437 if f == flag { 438 return true 439 } 440 } 441 return false 442} 443 444func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []string { 445 var result []string 446 for _, flag := range soongFlags { 447 skipFlag := false 448 for _, filter := range filterOut { 449 if filter != nil && filter(flag) { 450 skipFlag = true 451 } 452 } 453 if skipFlag { 454 continue 455 } 456 // Soong's cflags can contain spaces, like `-include header.h`. For 457 // Bazel's copts, split them up to be compatible with the 458 // no_copts_tokenization feature. 459 result = append(result, strings.Split(flag, " ")...) 460 } 461 return result 462} 463 464func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) { 465 // If there's arch specific srcs or exclude_srcs, generate a select entry for it. 466 // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too. 467 if srcsList, ok := parseSrcs(ctx, props); ok { 468 ca.srcs.SetSelectValue(axis, config, srcsList) 469 } 470 471 localIncludeDirs := props.Local_include_dirs 472 if axis == bazel.NoConfigAxis { 473 ca.cStd, ca.cppStd = bp2buildResolveCppStdValue(props.C_std, props.Cpp_std, props.Gnu_extensions) 474 if includeBuildDirectory(props.Include_build_directory) { 475 localIncludeDirs = append(localIncludeDirs, ".") 476 } 477 } 478 479 ca.absoluteIncludes.SetSelectValue(axis, config, props.Include_dirs) 480 ca.localIncludes.SetSelectValue(axis, config, localIncludeDirs) 481 482 instructionSet := proptools.StringDefault(props.Instruction_set, "") 483 if instructionSet == "arm" { 484 ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm", "-arm_isa_thumb"}) 485 } else if instructionSet != "" && instructionSet != "thumb" { 486 ctx.ModuleErrorf("Unknown value for instruction_set: %s", instructionSet) 487 } 488 489 // In Soong, cflags occur on the command line before -std=<val> flag, resulting in the value being 490 // overridden. In Bazel we always allow overriding, via flags; however, this can cause 491 // incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other 492 // cases. 493 ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags)) 494 ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil)) 495 ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags)) 496 ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags)) 497 ca.rtti.SetSelectValue(axis, config, props.Rtti) 498} 499 500func (ca *compilerAttributes) convertStlProps(ctx android.ArchVariantContext, module *Module) { 501 bp2BuildPropParseHelper(ctx, module, &StlProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 502 if stlProps, ok := props.(*StlProperties); ok { 503 if stlProps.Stl == nil { 504 return 505 } 506 if ca.stl == nil { 507 stl := deduplicateStlInput(*stlProps.Stl) 508 ca.stl = &stl 509 } else if ca.stl != stlProps.Stl { 510 ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *ca.stl, stlProps.Stl) 511 } 512 } 513 }) 514} 515 516func (ca *compilerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) { 517 productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{ 518 "Cflags": &ca.copts, 519 "Asflags": &ca.asFlags, 520 "Cppflags": &ca.cppFlags, 521 } 522 for propName, attr := range productVarPropNameToAttribute { 523 if productConfigProps, exists := productVariableProps[propName]; exists { 524 for productConfigProp, prop := range productConfigProps { 525 flags, ok := prop.([]string) 526 if !ok { 527 ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName)) 528 } 529 newFlags, _ := bazel.TryVariableSubstitutions(flags, productConfigProp.Name) 530 attr.SetSelectValue(productConfigProp.ConfigurationAxis(), productConfigProp.SelectKey(), newFlags) 531 } 532 } 533 } 534} 535 536func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, implementationHdrs bazel.LabelListAttribute) { 537 ca.srcs.ResolveExcludes() 538 partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs) 539 540 ca.protoSrcs = partitionedSrcs[protoSrcPartition] 541 ca.aidlSrcs = partitionedSrcs[aidlSrcPartition] 542 543 for p, lla := range partitionedSrcs { 544 // if there are no sources, there is no need for headers 545 if lla.IsEmpty() { 546 continue 547 } 548 lla.Append(implementationHdrs) 549 partitionedSrcs[p] = lla 550 } 551 552 ca.srcs = partitionedSrcs[cppSrcPartition] 553 ca.cSrcs = partitionedSrcs[cSrcPartition] 554 ca.asSrcs = partitionedSrcs[asSrcPartition] 555 ca.asmSrcs = partitionedSrcs[asmSrcPartition] 556 ca.lSrcs = partitionedSrcs[lSrcPartition] 557 ca.llSrcs = partitionedSrcs[llSrcPartition] 558 ca.syspropSrcs = partitionedSrcs[syspropSrcPartition] 559 560 ca.absoluteIncludes.DeduplicateAxesFromBase() 561 ca.localIncludes.DeduplicateAxesFromBase() 562} 563 564// Parse srcs from an arch or OS's props value. 565func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, bool) { 566 anySrcs := false 567 // Add srcs-like dependencies such as generated files. 568 // First create a LabelList containing these dependencies, then merge the values with srcs. 569 generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, props.Generated_sources, props.Exclude_generated_sources) 570 if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 { 571 anySrcs = true 572 } 573 574 allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs) 575 576 if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 { 577 anySrcs = true 578 } 579 580 return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs 581} 582 583func bp2buildStdVal(std *string, prefix string, useGnu bool) *string { 584 defaultVal := prefix + "_std_default" 585 // If c{,pp}std properties are not specified, don't generate them in the BUILD file. 586 // Defaults are handled by the toolchain definition. 587 // However, if gnu_extensions is false, then the default gnu-to-c version must be specified. 588 stdVal := proptools.StringDefault(std, defaultVal) 589 if stdVal == "experimental" || stdVal == defaultVal { 590 if stdVal == "experimental" { 591 stdVal = prefix + "_std_experimental" 592 } 593 if !useGnu { 594 stdVal += "_no_gnu" 595 } 596 } else if !useGnu { 597 stdVal = gnuToCReplacer.Replace(stdVal) 598 } 599 600 if stdVal == defaultVal { 601 return nil 602 } 603 return &stdVal 604} 605 606func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions *bool) (*string, *string) { 607 useGnu := useGnuExtensions(gnu_extensions) 608 609 return bp2buildStdVal(c_std, "c", useGnu), bp2buildStdVal(cpp_std, "cpp", useGnu) 610} 611 612// packageFromLabel extracts package from a fully-qualified or relative Label and whether the label 613// is fully-qualified. 614// e.g. fully-qualified "//a/b:foo" -> "a/b", true, relative: ":bar" -> ".", false 615func packageFromLabel(label string) (string, bool) { 616 split := strings.Split(label, ":") 617 if len(split) != 2 { 618 return "", false 619 } 620 if split[0] == "" { 621 return ".", false 622 } 623 // remove leading "//" 624 return split[0][2:], true 625} 626 627// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList> 628func includesFromLabelList(labelList bazel.LabelList) (relative, absolute []string) { 629 for _, hdr := range labelList.Includes { 630 if pkg, hasPkg := packageFromLabel(hdr.Label); hasPkg { 631 absolute = append(absolute, pkg) 632 } else if pkg != "" { 633 relative = append(relative, pkg) 634 } 635 } 636 return relative, absolute 637} 638 639type YasmAttributes struct { 640 Srcs bazel.LabelListAttribute 641 Flags bazel.StringListAttribute 642 Include_dirs bazel.StringListAttribute 643} 644 645func bp2BuildYasm(ctx android.Bp2buildMutatorContext, m *Module, ca compilerAttributes) *bazel.LabelAttribute { 646 if ca.asmSrcs.IsEmpty() { 647 return nil 648 } 649 650 // Yasm needs the include directories from both local_includes and 651 // export_include_dirs. We don't care about actually exporting them from the 652 // yasm rule though, because they will also be present on the cc_ rule that 653 // wraps this yasm rule. 654 includes := ca.localIncludes.Clone() 655 bp2BuildPropParseHelper(ctx, m, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 656 if flagExporterProperties, ok := props.(*FlagExporterProperties); ok { 657 if len(flagExporterProperties.Export_include_dirs) > 0 { 658 x := bazel.StringListAttribute{} 659 x.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs) 660 includes.Append(x) 661 } 662 } 663 }) 664 665 ctx.CreateBazelTargetModule( 666 bazel.BazelTargetModuleProperties{ 667 Rule_class: "yasm", 668 Bzl_load_location: "//build/bazel/rules/cc:yasm.bzl", 669 }, 670 android.CommonAttributes{Name: m.Name() + "_yasm"}, 671 &YasmAttributes{ 672 Srcs: ca.asmSrcs, 673 Flags: ca.asFlags, 674 Include_dirs: *includes, 675 }) 676 677 // We only want to add a dependency on the _yasm target if there are asm 678 // sources in the current configuration. If there are unconfigured asm 679 // sources, always add the dependency. Otherwise, add the dependency only 680 // on the configuration axes and values that had asm sources. 681 if len(ca.asmSrcs.Value.Includes) > 0 { 682 return bazel.MakeLabelAttribute(":" + m.Name() + "_yasm") 683 } 684 685 ret := &bazel.LabelAttribute{} 686 for _, axis := range ca.asmSrcs.SortedConfigurationAxes() { 687 for cfg := range ca.asmSrcs.ConfigurableValues[axis] { 688 ret.SetSelectValue(axis, cfg, bazel.Label{Label: ":" + m.Name() + "_yasm"}) 689 } 690 } 691 return ret 692} 693 694// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module.. 695func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes { 696 archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) 697 archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) 698 archVariantLibraryProperties := module.GetArchVariantProperties(ctx, &LibraryProperties{}) 699 700 var implementationHdrs bazel.LabelListAttribute 701 702 axisToConfigs := map[bazel.ConfigurationAxis]map[string]bool{} 703 allAxesAndConfigs := func(cp android.ConfigurationAxisToArchVariantProperties) { 704 for axis, configMap := range cp { 705 if _, ok := axisToConfigs[axis]; !ok { 706 axisToConfigs[axis] = map[string]bool{} 707 } 708 for cfg := range configMap { 709 axisToConfigs[axis][cfg] = true 710 } 711 } 712 } 713 allAxesAndConfigs(archVariantCompilerProps) 714 allAxesAndConfigs(archVariantLinkerProps) 715 allAxesAndConfigs(archVariantLibraryProperties) 716 717 compilerAttrs := compilerAttributes{} 718 linkerAttrs := linkerAttributes{} 719 720 // Iterate through these axes in a deterministic order. This is required 721 // because processing certain dependencies may result in concatenating 722 // elements along other axes. (For example, processing NoConfig may result 723 // in elements being added to InApex). This is thus the only way to ensure 724 // that the order of entries in each list is in a predictable order. 725 for _, axis := range bazel.SortedConfigurationAxes(axisToConfigs) { 726 configs := axisToConfigs[axis] 727 for cfg := range configs { 728 var allHdrs []string 729 if baseCompilerProps, ok := archVariantCompilerProps[axis][cfg].(*BaseCompilerProperties); ok { 730 allHdrs = baseCompilerProps.Generated_headers 731 if baseCompilerProps.Lex != nil { 732 compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags) 733 } 734 (&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps) 735 } 736 737 var exportHdrs []string 738 739 if baseLinkerProps, ok := archVariantLinkerProps[axis][cfg].(*BaseLinkerProperties); ok { 740 exportHdrs = baseLinkerProps.Export_generated_headers 741 742 (&linkerAttrs).bp2buildForAxisAndConfig(ctx, module, axis, cfg, baseLinkerProps) 743 } 744 headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportHdrs, android.BazelLabelForModuleDeps) 745 implementationHdrs.SetSelectValue(axis, cfg, headers.implementation) 746 compilerAttrs.hdrs.SetSelectValue(axis, cfg, headers.export) 747 748 exportIncludes, exportAbsoluteIncludes := includesFromLabelList(headers.export) 749 compilerAttrs.includes.Includes.SetSelectValue(axis, cfg, exportIncludes) 750 compilerAttrs.includes.AbsoluteIncludes.SetSelectValue(axis, cfg, exportAbsoluteIncludes) 751 752 includes, absoluteIncludes := includesFromLabelList(headers.implementation) 753 currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, cfg) 754 currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...)) 755 756 compilerAttrs.absoluteIncludes.SetSelectValue(axis, cfg, currAbsoluteIncludes) 757 758 currIncludes := compilerAttrs.localIncludes.SelectValue(axis, cfg) 759 currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...)) 760 761 compilerAttrs.localIncludes.SetSelectValue(axis, cfg, currIncludes) 762 763 if libraryProps, ok := archVariantLibraryProperties[axis][cfg].(*LibraryProperties); ok { 764 if axis == bazel.NoConfigAxis { 765 if libraryProps.Stubs.Symbol_file != nil { 766 compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file 767 versions := android.CopyOf(libraryProps.Stubs.Versions) 768 normalizeVersions(ctx, versions) 769 versions = addCurrentVersionIfNotPresent(versions) 770 compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, versions) 771 } 772 } 773 if suffix := libraryProps.Suffix; suffix != nil { 774 compilerAttrs.suffix.SetSelectValue(axis, cfg, suffix) 775 } 776 } 777 } 778 } 779 780 compilerAttrs.convertStlProps(ctx, module) 781 (&linkerAttrs).convertStripProps(ctx, module) 782 783 var nativeCoverage *bool 784 if module.coverage != nil && module.coverage.Properties.Native_coverage != nil && 785 !Bool(module.coverage.Properties.Native_coverage) { 786 nativeCoverage = BoolPtr(false) 787 } 788 789 productVariableProps := android.ProductVariableProperties(ctx, ctx.Module()) 790 791 (&compilerAttrs).convertProductVariables(ctx, productVariableProps) 792 (&linkerAttrs).convertProductVariables(ctx, productVariableProps) 793 794 (&compilerAttrs).finalize(ctx, implementationHdrs) 795 (&linkerAttrs).finalize(ctx) 796 797 (&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs)) 798 799 protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs) 800 801 // bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know 802 // which. This will add the newly generated proto library to the appropriate attribute and nothing 803 // to the other 804 (&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib) 805 (&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib) 806 807 aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs) 808 if aidlDep != nil { 809 if lib, ok := module.linker.(*libraryDecorator); ok { 810 if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) { 811 (&linkerAttrs).wholeArchiveDeps.Add(aidlDep) 812 } else { 813 (&linkerAttrs).implementationWholeArchiveDeps.Add(aidlDep) 814 } 815 } 816 } 817 818 convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs) 819 (&compilerAttrs).srcs.Add(&convertedLSrcs.srcName) 820 (&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName) 821 822 if module.afdo != nil && module.afdo.Properties.Afdo { 823 fdoProfileDep := bp2buildFdoProfile(ctx, module) 824 if fdoProfileDep != nil { 825 (&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep) 826 } 827 } 828 829 if !compilerAttrs.syspropSrcs.IsEmpty() { 830 (&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs)) 831 } 832 833 linkerAttrs.wholeArchiveDeps.Prepend = true 834 linkerAttrs.deps.Prepend = true 835 compilerAttrs.localIncludes.Prepend = true 836 compilerAttrs.absoluteIncludes.Prepend = true 837 compilerAttrs.hdrs.Prepend = true 838 839 features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(bp2buildSanitizerFeatures(ctx, module)) 840 features = features.Append(bp2buildLtoFeatures(ctx, module)) 841 features.DeduplicateAxesFromBase() 842 843 addMuslSystemDynamicDeps(ctx, linkerAttrs) 844 845 return baseAttributes{ 846 compilerAttrs, 847 linkerAttrs, 848 *features, 849 protoDep.protoDep, 850 aidlDep, 851 nativeCoverage, 852 } 853} 854 855// As a workaround for b/261657184, we are manually adding the default value 856// of system_dynamic_deps for the linux_musl os. 857// TODO: Solve this properly 858func addMuslSystemDynamicDeps(ctx android.Bp2buildMutatorContext, attrs linkerAttributes) { 859 systemDynamicDeps := attrs.systemDynamicDeps.SelectValue(bazel.OsConfigurationAxis, "linux_musl") 860 if attrs.systemDynamicDeps.HasAxisSpecificValues(bazel.OsConfigurationAxis) && systemDynamicDeps.IsNil() { 861 attrs.systemDynamicDeps.SetSelectValue(bazel.OsConfigurationAxis, "linux_musl", android.BazelLabelForModuleDeps(ctx, config.MuslDefaultSharedLibraries)) 862 } 863} 864 865type fdoProfileAttributes struct { 866 Absolute_path_profile string 867} 868 869func bp2buildFdoProfile( 870 ctx android.Bp2buildMutatorContext, 871 m *Module, 872) *bazel.Label { 873 for _, project := range globalAfdoProfileProjects { 874 // Ensure handcrafted BUILD file exists in the project 875 BUILDPath := android.ExistentPathForSource(ctx, project, "BUILD") 876 if BUILDPath.Valid() { 877 // We handcraft a BUILD file with fdo_profile targets that use the existing profiles in the project 878 // This implementation is assuming that every afdo profile in globalAfdoProfileProjects already has 879 // an associated fdo_profile target declared in the same package. 880 // TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`) 881 path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo") 882 if path.Valid() { 883 // FIXME: Some profiles only exist internally and are not released to AOSP. 884 // When generated BUILD files are checked in, we'll run into merge conflict. 885 // The cc_library_shared target in AOSP won't have reference to an fdo_profile target because 886 // the profile doesn't exist. Internally, the same cc_library_shared target will 887 // have reference to the fdo_profile. 888 // For more context, see b/258682955#comment2 889 fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name() 890 return &bazel.Label{ 891 Label: fdoProfileLabel, 892 } 893 } 894 } 895 } 896 897 return nil 898} 899 900func bp2buildCcAidlLibrary( 901 ctx android.Bp2buildMutatorContext, 902 m *Module, 903 aidlLabelList bazel.LabelListAttribute, 904 linkerAttrs linkerAttributes, 905) *bazel.LabelAttribute { 906 if !aidlLabelList.IsEmpty() { 907 aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool { 908 if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok && 909 fg.ShouldConvertToAidlLibrary(ctx) { 910 return true 911 } 912 return false 913 }) 914 915 apexAvailableTags := android.ApexAvailableTags(ctx.Module()) 916 sdkAttrs := bp2BuildParseSdkAttributes(m) 917 918 if !aidlSrcs.IsEmpty() { 919 aidlLibName := m.Name() + "_aidl_library" 920 ctx.CreateBazelTargetModule( 921 bazel.BazelTargetModuleProperties{ 922 Rule_class: "aidl_library", 923 Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl", 924 }, 925 android.CommonAttributes{Name: aidlLibName}, 926 &aidlLibraryAttributes{ 927 Srcs: aidlSrcs, 928 Tags: apexAvailableTags, 929 }, 930 ) 931 aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}}) 932 } 933 934 if !aidlLibs.IsEmpty() { 935 ccAidlLibrarylabel := m.Name() + "_cc_aidl_library" 936 // Since parent cc_library already has these dependencies, we can add them as implementation 937 // deps so that they don't re-export 938 implementationDeps := linkerAttrs.deps.Clone() 939 implementationDeps.Append(linkerAttrs.implementationDeps) 940 implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone() 941 implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps) 942 943 ctx.CreateBazelTargetModule( 944 bazel.BazelTargetModuleProperties{ 945 Rule_class: "cc_aidl_library", 946 Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl", 947 }, 948 android.CommonAttributes{Name: ccAidlLibrarylabel}, 949 &ccAidlLibraryAttributes{ 950 Deps: aidlLibs, 951 Implementation_deps: *implementationDeps, 952 Implementation_dynamic_deps: *implementationDynamicDeps, 953 Tags: apexAvailableTags, 954 sdkAttributes: sdkAttrs, 955 }, 956 ) 957 label := &bazel.LabelAttribute{ 958 Value: &bazel.Label{ 959 Label: ":" + ccAidlLibrarylabel, 960 }, 961 } 962 return label 963 } 964 } 965 966 return nil 967} 968 969func bp2BuildParseSdkAttributes(module *Module) sdkAttributes { 970 return sdkAttributes{ 971 Sdk_version: module.Properties.Sdk_version, 972 Min_sdk_version: module.Properties.Min_sdk_version, 973 } 974} 975 976type sdkAttributes struct { 977 Sdk_version *string 978 Min_sdk_version *string 979} 980 981// Convenience struct to hold all attributes parsed from linker properties. 982type linkerAttributes struct { 983 deps bazel.LabelListAttribute 984 implementationDeps bazel.LabelListAttribute 985 dynamicDeps bazel.LabelListAttribute 986 implementationDynamicDeps bazel.LabelListAttribute 987 runtimeDeps bazel.LabelListAttribute 988 wholeArchiveDeps bazel.LabelListAttribute 989 implementationWholeArchiveDeps bazel.LabelListAttribute 990 systemDynamicDeps bazel.LabelListAttribute 991 usedSystemDynamicDepAsDynamicDep map[string]bool 992 993 useVersionLib bazel.BoolAttribute 994 linkopts bazel.StringListAttribute 995 additionalLinkerInputs bazel.LabelListAttribute 996 stripKeepSymbols bazel.BoolAttribute 997 stripKeepSymbolsAndDebugFrame bazel.BoolAttribute 998 stripKeepSymbolsList bazel.StringListAttribute 999 stripAll bazel.BoolAttribute 1000 stripNone bazel.BoolAttribute 1001 features bazel.StringListAttribute 1002} 1003 1004var ( 1005 soongSystemSharedLibs = []string{"libc", "libm", "libdl"} 1006 versionLib = "libbuildversion" 1007) 1008 1009// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant 1010// since all libs are already excluded by default 1011func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, props *BaseLinkerProperties) { 1012 excludeSharedLibs := bazelLabelForSharedDeps(ctx, props.Target.Apex.Exclude_shared_libs) 1013 sharedExcludes := bazel.LabelList{Excludes: excludeSharedLibs.Includes} 1014 sharedExcludesLabelList := bazel.LabelListAttribute{} 1015 sharedExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, sharedExcludes) 1016 1017 la.dynamicDeps.Append(sharedExcludesLabelList) 1018 la.implementationDynamicDeps.Append(sharedExcludesLabelList) 1019 1020 excludeStaticLibs := bazelLabelForStaticDeps(ctx, props.Target.Apex.Exclude_static_libs) 1021 staticExcludes := bazel.LabelList{Excludes: excludeStaticLibs.Includes} 1022 staticExcludesLabelList := bazel.LabelListAttribute{} 1023 staticExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, staticExcludes) 1024 1025 la.deps.Append(staticExcludesLabelList) 1026 la.implementationDeps.Append(staticExcludesLabelList) 1027} 1028 1029func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) { 1030 isBinary := module.Binary() 1031 // Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module 1032 var axisFeatures []string 1033 1034 wholeStaticLibs := android.FirstUniqueStrings(props.Whole_static_libs) 1035 staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs)) 1036 if axis == bazel.NoConfigAxis { 1037 la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib) 1038 if proptools.Bool(props.Use_version_lib) { 1039 versionLibAlreadyInDeps := android.InList(versionLib, wholeStaticLibs) 1040 // remove from static libs so there is no duplicate dependency 1041 _, staticLibs = android.RemoveFromList(versionLib, staticLibs) 1042 // only add the dep if it is not in progress 1043 if !versionLibAlreadyInDeps { 1044 if isBinary { 1045 wholeStaticLibs = append(wholeStaticLibs, versionLib) 1046 } else { 1047 la.implementationWholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, []string{versionLib}, props.Exclude_static_libs)) 1048 } 1049 } 1050 } 1051 } 1052 1053 // Excludes to parallel Soong: 1054 // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0 1055 la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs)) 1056 1057 staticDeps := maybePartitionExportedAndImplementationsDepsExcludes( 1058 ctx, 1059 !isBinary, 1060 staticLibs, 1061 props.Exclude_static_libs, 1062 props.Export_static_lib_headers, 1063 bazelLabelForStaticDepsExcludes, 1064 ) 1065 1066 headerLibs := android.FirstUniqueStrings(props.Header_libs) 1067 hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, props.Export_header_lib_headers, bazelLabelForHeaderDeps) 1068 1069 (&hDeps.export).Append(staticDeps.export) 1070 la.deps.SetSelectValue(axis, config, hDeps.export) 1071 1072 (&hDeps.implementation).Append(staticDeps.implementation) 1073 la.implementationDeps.SetSelectValue(axis, config, hDeps.implementation) 1074 1075 systemSharedLibs := props.System_shared_libs 1076 // systemSharedLibs distinguishes between nil/empty list behavior: 1077 // nil -> use default values 1078 // empty list -> no values specified 1079 if len(systemSharedLibs) > 0 { 1080 systemSharedLibs = android.FirstUniqueStrings(systemSharedLibs) 1081 } 1082 la.systemDynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs)) 1083 1084 sharedLibs := android.FirstUniqueStrings(props.Shared_libs) 1085 excludeSharedLibs := props.Exclude_shared_libs 1086 usedSystem := android.FilterListPred(sharedLibs, func(s string) bool { 1087 return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs) 1088 }) 1089 for _, el := range usedSystem { 1090 if la.usedSystemDynamicDepAsDynamicDep == nil { 1091 la.usedSystemDynamicDepAsDynamicDep = map[string]bool{} 1092 } 1093 la.usedSystemDynamicDepAsDynamicDep[el] = true 1094 } 1095 1096 sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes( 1097 ctx, 1098 !isBinary, 1099 sharedLibs, 1100 props.Exclude_shared_libs, 1101 props.Export_shared_lib_headers, 1102 bazelLabelForSharedDepsExcludes, 1103 ) 1104 la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export) 1105 la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation) 1106 la.resolveTargetApexProp(ctx, props) 1107 1108 if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) { 1109 // If a dependency in la.implementationDynamicDeps or la.dynamicDeps has stubs, its 1110 // stub variant should be used when the dependency is linked in a APEX. The 1111 // dependencies in NoConfigAxis and OsConfigurationAxis/OsAndroid are grouped by 1112 // having stubs or not, so Bazel select() statement can be used to choose 1113 // source/stub variants of them. 1114 apexAvailable := module.ApexAvailable() 1115 setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, 0) 1116 setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, 1) 1117 } 1118 1119 if !BoolDefault(props.Pack_relocations, packRelocationsDefault) { 1120 axisFeatures = append(axisFeatures, "disable_pack_relocations") 1121 } 1122 1123 if Bool(props.Allow_undefined_symbols) { 1124 axisFeatures = append(axisFeatures, "-no_undefined_symbols") 1125 } 1126 1127 var linkerFlags []string 1128 if len(props.Ldflags) > 0 { 1129 linkerFlags = append(linkerFlags, proptools.NinjaEscapeList(props.Ldflags)...) 1130 // binaries remove static flag if -shared is in the linker flags 1131 if isBinary && android.InList("-shared", linkerFlags) { 1132 axisFeatures = append(axisFeatures, "-static_flag") 1133 } 1134 } 1135 1136 if !props.libCrt() { 1137 axisFeatures = append(axisFeatures, "-use_libcrt") 1138 } 1139 if !props.crt() { 1140 axisFeatures = append(axisFeatures, "-link_crt") 1141 } 1142 1143 // This must happen before the addition of flags for Version Script and 1144 // Dynamic List, as these flags must be split on spaces and those must not 1145 linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags) 1146 1147 additionalLinkerInputs := bazel.LabelList{} 1148 if props.Version_script != nil { 1149 label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script) 1150 additionalLinkerInputs.Add(&label) 1151 linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label)) 1152 } 1153 1154 if props.Dynamic_list != nil { 1155 label := android.BazelLabelForModuleSrcSingle(ctx, *props.Dynamic_list) 1156 additionalLinkerInputs.Add(&label) 1157 linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--dynamic-list,$(location %s)", label.Label)) 1158 } 1159 1160 la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs) 1161 la.linkopts.SetSelectValue(axis, config, linkerFlags) 1162 1163 if axisFeatures != nil { 1164 la.features.SetSelectValue(axis, config, axisFeatures) 1165 } 1166 1167 runtimeDeps := android.BazelLabelForModuleDepsExcludes(ctx, props.Runtime_libs, props.Exclude_runtime_libs) 1168 if !runtimeDeps.IsEmpty() { 1169 la.runtimeDeps.SetSelectValue(axis, config, runtimeDeps) 1170 } 1171} 1172 1173var ( 1174 apiSurfaceModuleLibCurrentPackage = "@api_surfaces//" + android.ModuleLibApi.String() + "/current:" 1175) 1176 1177func availableToSameApexes(a, b []string) bool { 1178 if len(a) == 0 && len(b) == 0 { 1179 return true 1180 } 1181 differ, _, _ := android.ListSetDifference(a, b) 1182 return !differ 1183} 1184 1185func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, 1186 config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int) { 1187 1188 depsWithStubs := []bazel.Label{} 1189 for _, l := range dynamicLibs.Includes { 1190 dep, _ := ctx.ModuleFromName(l.OriginalModuleName) 1191 if d, ok := dep.(*Module); ok && d.HasStubsVariants() { 1192 depApexAvailable := d.ApexAvailable() 1193 if !availableToSameApexes(apexAvailable, depApexAvailable) { 1194 depsWithStubs = append(depsWithStubs, l) 1195 } 1196 } 1197 } 1198 if len(depsWithStubs) > 0 { 1199 implDynamicDeps := bazel.SubtractBazelLabelList(dynamicLibs, bazel.MakeLabelList(depsWithStubs)) 1200 dynamicDeps.SetSelectValue(axis, config, implDynamicDeps) 1201 1202 stubLibLabels := []bazel.Label{} 1203 for _, l := range depsWithStubs { 1204 stubLabelInApiSurfaces := bazel.Label{ 1205 Label: apiSurfaceModuleLibCurrentPackage + strings.TrimPrefix(l.OriginalModuleName, ":"), 1206 } 1207 stubLibLabels = append(stubLibLabels, stubLabelInApiSurfaces) 1208 } 1209 inApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex) 1210 nonApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex) 1211 defaultSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey) 1212 if axis == bazel.NoConfigAxis { 1213 (&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels)) 1214 (&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs)) 1215 (&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs)) 1216 dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue)) 1217 dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue)) 1218 dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue)) 1219 } else if config == bazel.OsAndroid { 1220 (&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels)) 1221 (&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs)) 1222 dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue)) 1223 dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue)) 1224 } 1225 } 1226} 1227 1228func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { 1229 bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 1230 if stripProperties, ok := props.(*StripProperties); ok { 1231 la.stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols) 1232 la.stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list) 1233 la.stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame) 1234 la.stripAll.SetSelectValue(axis, config, stripProperties.Strip.All) 1235 la.stripNone.SetSelectValue(axis, config, stripProperties.Strip.None) 1236 } 1237 }) 1238} 1239 1240func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) { 1241 1242 type productVarDep struct { 1243 // the name of the corresponding excludes field, if one exists 1244 excludesField string 1245 // reference to the bazel attribute that should be set for the given product variable config 1246 attribute *bazel.LabelListAttribute 1247 1248 depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList 1249 } 1250 1251 // an intermediate attribute that holds Header_libs info, and will be appended to 1252 // implementationDeps at the end, to solve the confliction that both header_libs 1253 // and static_libs use implementationDeps. 1254 var headerDeps bazel.LabelListAttribute 1255 1256 productVarToDepFields := map[string]productVarDep{ 1257 // product variables do not support exclude_shared_libs 1258 "Shared_libs": {attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes}, 1259 "Static_libs": {"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes}, 1260 "Whole_static_libs": {"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes}, 1261 "Header_libs": {attribute: &headerDeps, depResolutionFunc: bazelLabelForHeaderDepsExcludes}, 1262 } 1263 1264 for name, dep := range productVarToDepFields { 1265 props, exists := productVariableProps[name] 1266 excludeProps, excludesExists := productVariableProps[dep.excludesField] 1267 // if neither an include nor excludes property exists, then skip it 1268 if !exists && !excludesExists { 1269 continue 1270 } 1271 // Collect all the configurations that an include or exclude property exists for. 1272 // We want to iterate all configurations rather than either the include or exclude because, for a 1273 // particular configuration, we may have either only an include or an exclude to handle. 1274 productConfigProps := make(map[android.ProductConfigProperty]bool, len(props)+len(excludeProps)) 1275 for p := range props { 1276 productConfigProps[p] = true 1277 } 1278 for p := range excludeProps { 1279 productConfigProps[p] = true 1280 } 1281 1282 for productConfigProp := range productConfigProps { 1283 prop, includesExists := props[productConfigProp] 1284 excludesProp, excludesExists := excludeProps[productConfigProp] 1285 var includes, excludes []string 1286 var ok bool 1287 // if there was no includes/excludes property, casting fails and that's expected 1288 if includes, ok = prop.([]string); includesExists && !ok { 1289 ctx.ModuleErrorf("Could not convert product variable %s property", name) 1290 } 1291 if excludes, ok = excludesProp.([]string); excludesExists && !ok { 1292 ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField) 1293 } 1294 1295 dep.attribute.EmitEmptyList = productConfigProp.AlwaysEmit() 1296 dep.attribute.SetSelectValue( 1297 productConfigProp.ConfigurationAxis(), 1298 productConfigProp.SelectKey(), 1299 dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes), 1300 ) 1301 } 1302 } 1303 la.implementationDeps.Append(headerDeps) 1304} 1305 1306func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) { 1307 // if system dynamic deps have the default value, any use of a system dynamic library used will 1308 // result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries 1309 // from bionic OSes and the no config case as these libraries only build for bionic OSes. 1310 if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 { 1311 toRemove := bazelLabelForSharedDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsDynamicDep)) 1312 la.dynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove) 1313 la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove) 1314 la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove) 1315 la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove) 1316 la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove) 1317 la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove) 1318 1319 la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, toRemove) 1320 la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, toRemove) 1321 stubsToRemove := make([]bazel.Label, 0, len(la.usedSystemDynamicDepAsDynamicDep)) 1322 for _, lib := range toRemove.Includes { 1323 stubLabelInApiSurfaces := bazel.Label{ 1324 Label: apiSurfaceModuleLibCurrentPackage + lib.OriginalModuleName, 1325 } 1326 stubsToRemove = append(stubsToRemove, stubLabelInApiSurfaces) 1327 } 1328 la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.MakeLabelList(stubsToRemove)) 1329 } 1330 1331 la.deps.ResolveExcludes() 1332 la.implementationDeps.ResolveExcludes() 1333 la.dynamicDeps.ResolveExcludes() 1334 la.implementationDynamicDeps.ResolveExcludes() 1335 la.wholeArchiveDeps.ResolveExcludes() 1336 la.systemDynamicDeps.ForceSpecifyEmptyList = true 1337 1338} 1339 1340// Relativize a list of root-relative paths with respect to the module's 1341// directory. 1342// 1343// include_dirs Soong prop are root-relative (b/183742505), but 1344// local_include_dirs, export_include_dirs and export_system_include_dirs are 1345// module dir relative. This function makes a list of paths entirely module dir 1346// relative. 1347// 1348// For the `include` attribute, Bazel wants the paths to be relative to the 1349// module. 1350func bp2BuildMakePathsRelativeToModule(ctx android.BazelConversionPathContext, paths []string) []string { 1351 var relativePaths []string 1352 for _, path := range paths { 1353 // Semantics of filepath.Rel: join(ModuleDir, rel(ModuleDir, path)) == path 1354 relativePath, err := filepath.Rel(ctx.ModuleDir(), path) 1355 if err != nil { 1356 panic(err) 1357 } 1358 relativePaths = append(relativePaths, relativePath) 1359 } 1360 return relativePaths 1361} 1362 1363// BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel 1364// attributes. 1365type BazelIncludes struct { 1366 AbsoluteIncludes bazel.StringListAttribute 1367 Includes bazel.StringListAttribute 1368 SystemIncludes bazel.StringListAttribute 1369} 1370 1371func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module, includes *BazelIncludes) BazelIncludes { 1372 var exported BazelIncludes 1373 if includes != nil { 1374 exported = *includes 1375 } else { 1376 exported = BazelIncludes{} 1377 } 1378 1379 // cc library Export_include_dirs and Export_system_include_dirs are marked 1380 // "variant_prepend" in struct tag, set their prepend property to true to make 1381 // sure bp2build generates correct result. 1382 exported.Includes.Prepend = true 1383 exported.SystemIncludes.Prepend = true 1384 1385 bp2BuildPropParseHelper(ctx, module, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 1386 if flagExporterProperties, ok := props.(*FlagExporterProperties); ok { 1387 if len(flagExporterProperties.Export_include_dirs) > 0 { 1388 exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...))) 1389 } 1390 if len(flagExporterProperties.Export_system_include_dirs) > 0 { 1391 exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...))) 1392 } 1393 } 1394 }) 1395 exported.AbsoluteIncludes.DeduplicateAxesFromBase() 1396 exported.Includes.DeduplicateAxesFromBase() 1397 exported.SystemIncludes.DeduplicateAxesFromBase() 1398 1399 return exported 1400} 1401 1402func BazelLabelNameForStaticModule(baseLabel string) string { 1403 return baseLabel + "_bp2build_cc_library_static" 1404} 1405 1406func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string { 1407 label := android.BazelModuleLabel(ctx, m) 1408 if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary { 1409 return BazelLabelNameForStaticModule(label) 1410 } 1411 return label 1412} 1413 1414func bazelLabelForSharedModule(ctx android.BazelConversionPathContext, m blueprint.Module) string { 1415 // cc_library, at it's root name, propagates the shared library, which depends on the static 1416 // library. 1417 return android.BazelModuleLabel(ctx, m) 1418} 1419 1420func bazelLabelForStaticWholeModuleDeps(ctx android.BazelConversionPathContext, m blueprint.Module) string { 1421 label := bazelLabelForStaticModule(ctx, m) 1422 if aModule, ok := m.(android.Module); ok { 1423 if android.IsModulePrebuilt(aModule) { 1424 label += "_alwayslink" 1425 } 1426 } 1427 return label 1428} 1429 1430func bazelLabelForWholeDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList { 1431 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps) 1432} 1433 1434func bazelLabelForWholeDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { 1435 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps) 1436} 1437 1438func bazelLabelForStaticDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { 1439 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule) 1440} 1441 1442func bazelLabelForStaticDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList { 1443 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule) 1444} 1445 1446func bazelLabelForSharedDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList { 1447 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule) 1448} 1449 1450func bazelLabelForHeaderDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList { 1451 // This is not elegant, but bp2build's shared library targets only propagate 1452 // their header information as part of the normal C++ provider. 1453 return bazelLabelForSharedDeps(ctx, modules) 1454} 1455 1456func bazelLabelForHeaderDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { 1457 // This is only used when product_variable header_libs is processed, to follow 1458 // the pattern of depResolutionFunc 1459 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule) 1460} 1461 1462func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { 1463 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule) 1464} 1465 1466type binaryLinkerAttrs struct { 1467 Linkshared *bool 1468 Suffix bazel.StringAttribute 1469} 1470 1471func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs { 1472 attrs := binaryLinkerAttrs{} 1473 bp2BuildPropParseHelper(ctx, m, &BinaryLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 1474 linkerProps := props.(*BinaryLinkerProperties) 1475 staticExecutable := linkerProps.Static_executable 1476 if axis == bazel.NoConfigAxis { 1477 if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared { 1478 attrs.Linkshared = &linkBinaryShared 1479 } 1480 } else if staticExecutable != nil { 1481 // TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a 1482 // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling 1483 ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values") 1484 } 1485 if suffix := linkerProps.Suffix; suffix != nil { 1486 attrs.Suffix.SetSelectValue(axis, config, suffix) 1487 } 1488 }) 1489 1490 return attrs 1491} 1492 1493func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute { 1494 sanitizerFeatures := bazel.StringListAttribute{} 1495 bp2BuildPropParseHelper(ctx, m, &SanitizeProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 1496 var features []string 1497 if sanitizerProps, ok := props.(*SanitizeProperties); ok { 1498 if sanitizerProps.Sanitize.Integer_overflow != nil && *sanitizerProps.Sanitize.Integer_overflow { 1499 features = append(features, "ubsan_integer_overflow") 1500 } 1501 for _, sanitizer := range sanitizerProps.Sanitize.Misc_undefined { 1502 features = append(features, "ubsan_"+sanitizer) 1503 } 1504 sanitizerFeatures.SetSelectValue(axis, config, features) 1505 } 1506 }) 1507 return sanitizerFeatures 1508} 1509 1510func bp2buildLtoFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute { 1511 lto_feature_name := "android_thin_lto" 1512 ltoBoolFeatures := bazel.BoolAttribute{} 1513 bp2BuildPropParseHelper(ctx, m, <OProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { 1514 if ltoProps, ok := props.(*LTOProperties); ok { 1515 thinProp := ltoProps.Lto.Thin != nil && *ltoProps.Lto.Thin 1516 thinPropSetToFalse := ltoProps.Lto.Thin != nil && !*ltoProps.Lto.Thin 1517 neverProp := ltoProps.Lto.Never != nil && *ltoProps.Lto.Never 1518 if thinProp { 1519 ltoBoolFeatures.SetSelectValue(axis, config, BoolPtr(true)) 1520 return 1521 } 1522 if neverProp || thinPropSetToFalse { 1523 if thinProp { 1524 ctx.ModuleErrorf("lto.thin and lto.never are mutually exclusive but were specified together") 1525 } else { 1526 ltoBoolFeatures.SetSelectValue(axis, config, BoolPtr(false)) 1527 } 1528 return 1529 } 1530 } 1531 ltoBoolFeatures.SetSelectValue(axis, config, nil) 1532 }) 1533 1534 props := m.GetArchVariantProperties(ctx, <OProperties{}) 1535 ltoStringFeatures, err := ltoBoolFeatures.ToStringListAttribute(func(boolPtr *bool, axis bazel.ConfigurationAxis, config string) []string { 1536 if boolPtr == nil { 1537 return []string{} 1538 } 1539 if !*boolPtr { 1540 return []string{"-" + lto_feature_name} 1541 } 1542 features := []string{lto_feature_name} 1543 if ltoProps, ok := props[axis][config].(*LTOProperties); ok { 1544 if ltoProps.Whole_program_vtables != nil && *ltoProps.Whole_program_vtables { 1545 features = append(features, "android_thin_lto_whole_program_vtables") 1546 } 1547 } 1548 return features 1549 }) 1550 if err != nil { 1551 ctx.ModuleErrorf("Error processing LTO attributes: %s", err) 1552 } 1553 return ltoStringFeatures 1554} 1555