blob: ec15b26db0c15666873a08d2648eb65e1da33dee [file] [log] [blame]
Jingwen Chen91220d72021-03-24 02:18:33 -04001// 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 (
Jingwen Chened9c17d2021-04-13 07:14:55 +000017 "path/filepath"
Jingwen Chen3950cd62021-05-12 04:33:00 +000018 "strings"
Chris Parsons484e50a2021-05-13 15:13:04 -040019
20 "android/soong/android"
21 "android/soong/bazel"
Liz Kammer7a210ac2021-09-22 15:52:58 -040022
Chris Parsons953b3562021-09-20 15:14:39 -040023 "github.com/google/blueprint"
Liz Kammerba7a9c52021-05-26 08:45:30 -040024
25 "github.com/google/blueprint/proptools"
Jingwen Chen91220d72021-03-24 02:18:33 -040026)
27
Liz Kammer2222c6b2021-05-24 15:41:47 -040028// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
Jingwen Chenbcf53042021-05-26 04:42:42 +000029// properties which apply to either the shared or static version of a cc_library module.
Liz Kammer2222c6b2021-05-24 15:41:47 -040030type staticOrSharedAttributes struct {
Jingwen Chenc4dc9b42021-06-11 12:51:48 +000031 Srcs bazel.LabelListAttribute
32 Srcs_c bazel.LabelListAttribute
33 Srcs_as bazel.LabelListAttribute
34 Copts bazel.StringListAttribute
Jingwen Chen14a8bda2021-06-02 11:10:02 +000035
Liz Kammer7a210ac2021-09-22 15:52:58 -040036 Deps bazel.LabelListAttribute
37 Implementation_deps bazel.LabelListAttribute
38 Dynamic_deps bazel.LabelListAttribute
39 Implementation_dynamic_deps bazel.LabelListAttribute
40 Whole_archive_deps bazel.LabelListAttribute
Chris Parsons51f8c392021-08-03 21:01:05 -040041
42 System_dynamic_deps bazel.LabelListAttribute
Jingwen Chen53681ef2021-04-29 08:15:13 +000043}
44
Jingwen Chen14a8bda2021-06-02 11:10:02 +000045func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) {
Jingwen Chen14a8bda2021-06-02 11:10:02 +000046 // Check that a module is a filegroup type named <label>.
47 isFilegroupNamed := func(m android.Module, fullLabel string) bool {
48 if ctx.OtherModuleType(m) != "filegroup" {
49 return false
50 }
51 labelParts := strings.Split(fullLabel, ":")
52 if len(labelParts) > 2 {
53 // There should not be more than one colon in a label.
Liz Kammer57e2e7a2021-09-20 12:55:02 -040054 ctx.ModuleErrorf("%s is not a valid Bazel label for a filegroup", fullLabel)
Jingwen Chen14a8bda2021-06-02 11:10:02 +000055 }
Liz Kammer57e2e7a2021-09-20 12:55:02 -040056 return m.Name() == labelParts[len(labelParts)-1]
Jingwen Chen14a8bda2021-06-02 11:10:02 +000057 }
58
Liz Kammer57e2e7a2021-09-20 12:55:02 -040059 // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
60 // macro.
61 addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
62 return func(ctx bazel.OtherModuleContext, label string) (string, bool) {
63 m, exists := ctx.ModuleFromName(label)
64 if !exists {
65 return label, false
Jingwen Chen14a8bda2021-06-02 11:10:02 +000066 }
Chris Parsons5a34ffb2021-07-21 14:34:58 -040067 aModule, _ := m.(android.Module)
Liz Kammer57e2e7a2021-09-20 12:55:02 -040068 if !isFilegroupNamed(aModule, label) {
69 return label, false
Jingwen Chen14a8bda2021-06-02 11:10:02 +000070 }
Liz Kammer57e2e7a2021-09-20 12:55:02 -040071 return label + suffix, true
Chris Parsons5a34ffb2021-07-21 14:34:58 -040072 }
Jingwen Chen14a8bda2021-06-02 11:10:02 +000073 }
74
Liz Kammer57e2e7a2021-09-20 12:55:02 -040075 // TODO(b/190006308): Handle language detection of sources in a Bazel rule.
76 partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
77 "c": bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
78 "as": bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
79 // C++ is the "catch-all" group, and comprises generated sources because we don't
80 // know the language of these sources until the genrule is executed.
81 "cpp": bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
82 })
Jingwen Chen14a8bda2021-06-02 11:10:02 +000083
Liz Kammer57e2e7a2021-09-20 12:55:02 -040084 cSrcs = partitioned["c"]
85 asSrcs = partitioned["as"]
86 cppSrcs = partitioned["cpp"]
Jingwen Chen14a8bda2021-06-02 11:10:02 +000087 return
88}
89
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxac5097f2021-09-01 21:22:09 +000090// bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
91func bp2BuildParseLibProps(ctx android.TopDownMutatorContext, module *Module, isStatic bool) staticOrSharedAttributes {
Jingwen Chen53681ef2021-04-29 08:15:13 +000092 lib, ok := module.compiler.(*libraryDecorator)
93 if !ok {
Liz Kammer2222c6b2021-05-24 15:41:47 -040094 return staticOrSharedAttributes{}
Jingwen Chen53681ef2021-04-29 08:15:13 +000095 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxac5097f2021-09-01 21:22:09 +000096 return bp2buildParseStaticOrSharedProps(ctx, module, lib, isStatic)
97}
Jingwen Chen53681ef2021-04-29 08:15:13 +000098
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxac5097f2021-09-01 21:22:09 +000099// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
100func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
101 return bp2BuildParseLibProps(ctx, module, false)
Jingwen Chen53681ef2021-04-29 08:15:13 +0000102}
103
104// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
Liz Kammer2222c6b2021-05-24 15:41:47 -0400105func bp2BuildParseStaticProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxac5097f2021-09-01 21:22:09 +0000106 return bp2BuildParseLibProps(ctx, module, true)
Liz Kammer2222c6b2021-05-24 15:41:47 -0400107}
108
Liz Kammer7a210ac2021-09-22 15:52:58 -0400109type depsPartition struct {
110 export bazel.LabelList
111 implementation bazel.LabelList
112}
113
114type bazelLabelForDepsFn func(android.TopDownMutatorContext, []string) bazel.LabelList
115
116func partitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
117 implementation, export := android.FilterList(allDeps, exportedDeps)
118
119 return depsPartition{
120 export: fn(ctx, export),
121 implementation: fn(ctx, implementation),
122 }
123}
124
125type bazelLabelForDepsExcludesFn func(android.TopDownMutatorContext, []string, []string) bazel.LabelList
126
127func partitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
128 implementation, export := android.FilterList(allDeps, exportedDeps)
129
130 return depsPartition{
131 export: fn(ctx, export, excludes),
132 implementation: fn(ctx, implementation, excludes),
133 }
134}
135
Jingwen Chenbcf53042021-05-26 04:42:42 +0000136func bp2buildParseStaticOrSharedProps(ctx android.TopDownMutatorContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
Liz Kammer135bf552021-08-11 10:46:06 -0400137 attrs := staticOrSharedAttributes{}
Jingwen Chenbcf53042021-05-26 04:42:42 +0000138
Liz Kammer9abd62d2021-05-21 08:37:59 -0400139 setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
Jingwen Chenc4dc9b42021-06-11 12:51:48 +0000140 attrs.Copts.SetSelectValue(axis, config, props.Cflags)
141 attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
Chris Parsons953b3562021-09-20 15:14:39 -0400142 attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
Liz Kammer7a210ac2021-09-22 15:52:58 -0400143
144 staticDeps := partitionExportedAndImplementationsDeps(ctx, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps)
145 attrs.Deps.SetSelectValue(axis, config, staticDeps.export)
146 attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation)
147
148 sharedDeps := partitionExportedAndImplementationsDeps(ctx, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps)
149 attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export)
150 attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
151
152 attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
Jingwen Chenbcf53042021-05-26 04:42:42 +0000153 }
Liz Kammer135bf552021-08-11 10:46:06 -0400154 // system_dynamic_deps distinguishes between nil/empty list behavior:
155 // nil -> use default values
156 // empty list -> no values specified
157 attrs.System_dynamic_deps.ForceSpecifyEmptyList = true
Jingwen Chenbcf53042021-05-26 04:42:42 +0000158
159 if isStatic {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400160 for axis, configToProps := range module.GetArchVariantProperties(ctx, &StaticProperties{}) {
161 for config, props := range configToProps {
162 if staticOrSharedProps, ok := props.(*StaticProperties); ok {
163 setAttrs(axis, config, staticOrSharedProps.Static)
Jingwen Chenbcf53042021-05-26 04:42:42 +0000164 }
165 }
166 }
167 } else {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400168 for axis, configToProps := range module.GetArchVariantProperties(ctx, &SharedProperties{}) {
169 for config, props := range configToProps {
170 if staticOrSharedProps, ok := props.(*SharedProperties); ok {
171 setAttrs(axis, config, staticOrSharedProps.Shared)
Jingwen Chenbcf53042021-05-26 04:42:42 +0000172 }
173 }
174 }
175 }
176
Jingwen Chenc4dc9b42021-06-11 12:51:48 +0000177 cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.Srcs)
178 attrs.Srcs = cppSrcs
179 attrs.Srcs_c = cSrcs
180 attrs.Srcs_as = asSrcs
Jingwen Chen14a8bda2021-06-02 11:10:02 +0000181
Jingwen Chenbcf53042021-05-26 04:42:42 +0000182 return attrs
Jingwen Chen53681ef2021-04-29 08:15:13 +0000183}
184
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400185// Convenience struct to hold all attributes parsed from prebuilt properties.
186type prebuiltAttributes struct {
187 Src bazel.LabelAttribute
188}
189
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxac5097f2021-09-01 21:22:09 +0000190// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400191func Bp2BuildParsePrebuiltLibraryProps(ctx android.TopDownMutatorContext, module *Module) prebuiltAttributes {
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400192 var srcLabelAttribute bazel.LabelAttribute
193
Liz Kammer9abd62d2021-05-21 08:37:59 -0400194 for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltLinkerProperties{}) {
195 for config, props := range configToProps {
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400196 if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok {
197 if len(prebuiltLinkerProperties.Srcs) > 1 {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400198 ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most once source file for %s %s\n", axis, config)
199 continue
200 } else if len(prebuiltLinkerProperties.Srcs) == 0 {
201 continue
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400202 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400203 src := android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinkerProperties.Srcs[0])
204 srcLabelAttribute.SetSelectValue(axis, config, src)
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400205 }
206 }
207 }
208
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400209 return prebuiltAttributes{
210 Src: srcLabelAttribute,
211 }
212}
213
Jingwen Chen107c0de2021-04-09 10:43:12 +0000214// Convenience struct to hold all attributes parsed from compiler properties.
215type compilerAttributes struct {
Chris Parsons990c4f42021-05-25 12:10:58 -0400216 // Options for all languages
217 copts bazel.StringListAttribute
218 // Assembly options and sources
219 asFlags bazel.StringListAttribute
220 asSrcs bazel.LabelListAttribute
221 // C options and sources
222 conlyFlags bazel.StringListAttribute
223 cSrcs bazel.LabelListAttribute
224 // C++ options and sources
225 cppFlags bazel.StringListAttribute
Jingwen Chened9c17d2021-04-13 07:14:55 +0000226 srcs bazel.LabelListAttribute
Chris Parsons2c788392021-08-10 11:58:07 -0400227
228 rtti bazel.BoolAttribute
Chris Parsonsa967f252021-09-23 16:34:35 -0400229 stl *string
Liz Kammer35687bc2021-09-10 10:07:07 -0400230
231 localIncludes bazel.StringListAttribute
232 absoluteIncludes bazel.StringListAttribute
Jingwen Chen107c0de2021-04-09 10:43:12 +0000233}
234
Jingwen Chen63930982021-03-24 10:04:33 -0400235// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
Jingwen Chen107c0de2021-04-09 10:43:12 +0000236func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Module) compilerAttributes {
Jingwen Chen882bcc12021-04-27 05:54:20 +0000237 var srcs bazel.LabelListAttribute
Jingwen Chen107c0de2021-04-09 10:43:12 +0000238 var copts bazel.StringListAttribute
Chris Parsons990c4f42021-05-25 12:10:58 -0400239 var asFlags bazel.StringListAttribute
240 var conlyFlags bazel.StringListAttribute
241 var cppFlags bazel.StringListAttribute
Chris Parsons2c788392021-08-10 11:58:07 -0400242 var rtti bazel.BoolAttribute
Liz Kammer35687bc2021-09-10 10:07:07 -0400243 var localIncludes bazel.StringListAttribute
244 var absoluteIncludes bazel.StringListAttribute
Jingwen Chened9c17d2021-04-13 07:14:55 +0000245
Chris Parsons990c4f42021-05-25 12:10:58 -0400246 parseCommandLineFlags := func(soongFlags []string) []string {
247 var result []string
248 for _, flag := range soongFlags {
Colin Cross52aa4e12021-05-25 15:20:39 +0000249 // Soong's cflags can contain spaces, like `-include header.h`. For
250 // Bazel's copts, split them up to be compatible with the
251 // no_copts_tokenization feature.
Chris Parsons990c4f42021-05-25 12:10:58 -0400252 result = append(result, strings.Split(flag, " ")...)
Colin Cross52aa4e12021-05-25 15:20:39 +0000253 }
Chris Parsons990c4f42021-05-25 12:10:58 -0400254 return result
255 }
256
Liz Kammer74deed42021-06-02 13:02:03 -0400257 // Parse srcs from an arch or OS's props value.
Jingwen Chene32e9e02021-04-23 09:17:24 +0000258 parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
Chris Parsons484e50a2021-05-13 15:13:04 -0400259 // Add srcs-like dependencies such as generated files.
260 // First create a LabelList containing these dependencies, then merge the values with srcs.
261 generatedHdrsAndSrcs := baseCompilerProps.Generated_headers
262 generatedHdrsAndSrcs = append(generatedHdrsAndSrcs, baseCompilerProps.Generated_sources...)
Chris Parsons484e50a2021-05-13 15:13:04 -0400263 generatedHdrsAndSrcsLabelList := android.BazelLabelForModuleDeps(ctx, generatedHdrsAndSrcs)
264
Liz Kammer74deed42021-06-02 13:02:03 -0400265 allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs)
Chris Parsons484e50a2021-05-13 15:13:04 -0400266 return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedHdrsAndSrcsLabelList)
Jingwen Chene32e9e02021-04-23 09:17:24 +0000267 }
268
Liz Kammer9abd62d2021-05-21 08:37:59 -0400269 archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
Liz Kammer9abd62d2021-05-21 08:37:59 -0400270 for axis, configToProps := range archVariantCompilerProps {
271 for config, props := range configToProps {
272 if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
273 // If there's arch specific srcs or exclude_srcs, generate a select entry for it.
274 // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
275 if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
276 srcsList := parseSrcs(baseCompilerProps)
277 srcs.SetSelectValue(axis, config, srcsList)
Liz Kammer9abd62d2021-05-21 08:37:59 -0400278 }
279
Jingwen Chen97b85312021-10-08 10:41:31 +0000280 var archVariantCopts []string
281 if axis == bazel.NoConfigAxis {
282 // If cpp_std is not specified, don't generate it in the
283 // BUILD file. For readability purposes, cpp_std and gnu_extensions are
284 // combined into a single -std=<version> copt, except in the
285 // default case where cpp_std is nil and gnu_extensions is true or unspecified,
286 // then the toolchain's default "gnu++17" will be used.
287 if baseCompilerProps.Cpp_std != nil {
288 // TODO(b/202491296): Handle C_std.
289 // These transformations are shared with compiler.go.
290 cppStdVal := parseCppStd(baseCompilerProps.Cpp_std)
291 _, cppStdVal = maybeReplaceGnuToC(baseCompilerProps.Gnu_extensions, "", cppStdVal)
292 archVariantCopts = append(archVariantCopts, "-std="+cppStdVal)
293 } else if baseCompilerProps.Gnu_extensions != nil && !*baseCompilerProps.Gnu_extensions {
294 archVariantCopts = append(archVariantCopts, "-std=c++17")
295 }
296 }
297 archVariantCopts = append(archVariantCopts, parseCommandLineFlags(baseCompilerProps.Cflags)...)
Chris Parsons69fa9f92021-07-13 11:47:44 -0400298 archVariantAsflags := parseCommandLineFlags(baseCompilerProps.Asflags)
Liz Kammer35687bc2021-09-10 10:07:07 -0400299
300 localIncludeDirs := baseCompilerProps.Local_include_dirs
301 if axis == bazel.NoConfigAxis && includeBuildDirectory(baseCompilerProps.Include_build_directory) {
302 localIncludeDirs = append(localIncludeDirs, ".")
Chris Parsons69fa9f92021-07-13 11:47:44 -0400303 }
304
Liz Kammer35687bc2021-09-10 10:07:07 -0400305 absoluteIncludes.SetSelectValue(axis, config, baseCompilerProps.Include_dirs)
306 localIncludes.SetSelectValue(axis, config, localIncludeDirs)
Liz Kammer135bf552021-08-11 10:46:06 -0400307
Chris Parsons69fa9f92021-07-13 11:47:44 -0400308 copts.SetSelectValue(axis, config, archVariantCopts)
309 asFlags.SetSelectValue(axis, config, archVariantAsflags)
Liz Kammer9abd62d2021-05-21 08:37:59 -0400310 conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Conlyflags))
311 cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Cppflags))
Chris Parsons2c788392021-08-10 11:58:07 -0400312 rtti.SetSelectValue(axis, config, baseCompilerProps.Rtti)
Liz Kammer9abd62d2021-05-21 08:37:59 -0400313 }
Jingwen Chenc1c26502021-04-05 10:35:13 +0000314 }
315 }
316
Liz Kammer74deed42021-06-02 13:02:03 -0400317 srcs.ResolveExcludes()
Liz Kammer35687bc2021-09-10 10:07:07 -0400318 absoluteIncludes.DeduplicateAxesFromBase()
319 localIncludes.DeduplicateAxesFromBase()
Jingwen Chenc1c26502021-04-05 10:35:13 +0000320
Liz Kammerba7a9c52021-05-26 08:45:30 -0400321 productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{
322 "Cflags": &copts,
323 "Asflags": &asFlags,
324 "CppFlags": &cppFlags,
325 }
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400326 productVariableProps := android.ProductVariableProperties(ctx)
Liz Kammerba7a9c52021-05-26 08:45:30 -0400327 for propName, attr := range productVarPropNameToAttribute {
328 if props, exists := productVariableProps[propName]; exists {
329 for _, prop := range props {
330 flags, ok := prop.Property.([]string)
331 if !ok {
332 ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
333 }
334 newFlags, _ := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable)
Liz Kammer47535c52021-06-02 16:02:22 -0400335 attr.SetSelectValue(bazel.ProductVariableConfigurationAxis(prop.FullConfig), prop.FullConfig, newFlags)
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400336 }
Liz Kammer6fd7b3f2021-05-06 13:54:29 -0400337 }
338 }
339
Jingwen Chen14a8bda2021-06-02 11:10:02 +0000340 srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs)
341
Chris Parsonsa967f252021-09-23 16:34:35 -0400342 var stl *string = nil
343 stlPropsByArch := module.GetArchVariantProperties(ctx, &StlProperties{})
344 for _, configToProps := range stlPropsByArch {
345 for _, props := range configToProps {
346 if stlProps, ok := props.(*StlProperties); ok {
347 if stlProps.Stl != nil {
348 if stl == nil {
349 stl = stlProps.Stl
350 } else {
351 if stl != stlProps.Stl {
352 ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *stl, stlProps.Stl)
353 }
354 }
355 }
356 }
357 }
358 }
359
Jingwen Chen107c0de2021-04-09 10:43:12 +0000360 return compilerAttributes{
Liz Kammer35687bc2021-09-10 10:07:07 -0400361 copts: copts,
362 srcs: srcs,
363 asFlags: asFlags,
364 asSrcs: asSrcs,
365 cSrcs: cSrcs,
366 conlyFlags: conlyFlags,
367 cppFlags: cppFlags,
368 rtti: rtti,
Chris Parsonsa967f252021-09-23 16:34:35 -0400369 stl: stl,
Liz Kammer35687bc2021-09-10 10:07:07 -0400370 localIncludes: localIncludes,
371 absoluteIncludes: absoluteIncludes,
Jingwen Chen107c0de2021-04-09 10:43:12 +0000372 }
373}
374
375// Convenience struct to hold all attributes parsed from linker properties.
376type linkerAttributes struct {
Liz Kammer7a210ac2021-09-22 15:52:58 -0400377 deps bazel.LabelListAttribute
378 implementationDeps bazel.LabelListAttribute
379 dynamicDeps bazel.LabelListAttribute
380 implementationDynamicDeps bazel.LabelListAttribute
381 wholeArchiveDeps bazel.LabelListAttribute
382 systemDynamicDeps bazel.LabelListAttribute
383
Jingwen Chen6ada5892021-09-17 11:38:09 +0000384 linkCrt bazel.BoolAttribute
Jingwen Chen3d383bb2021-06-09 07:18:37 +0000385 useLibcrt bazel.BoolAttribute
386 linkopts bazel.StringListAttribute
387 versionScript bazel.LabelAttribute
388 stripKeepSymbols bazel.BoolAttribute
389 stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
390 stripKeepSymbolsList bazel.StringListAttribute
391 stripAll bazel.BoolAttribute
392 stripNone bazel.BoolAttribute
Jingwen Chenc1c26502021-04-05 10:35:13 +0000393}
394
Rupert Shuttleworth143be942021-05-09 23:55:51 -0400395// FIXME(b/187655838): Use the existing linkerFlags() function instead of duplicating logic here
396func getBp2BuildLinkerFlags(linkerProperties *BaseLinkerProperties) []string {
397 flags := linkerProperties.Ldflags
398 if !BoolDefault(linkerProperties.Pack_relocations, true) {
399 flags = append(flags, "-Wl,--pack-dyn-relocs=none")
400 }
401 return flags
402}
403
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200404// bp2BuildParseLinkerProps parses the linker properties of a module, including
Jingwen Chen91220d72021-03-24 02:18:33 -0400405// configurable attribute values.
Jingwen Chen107c0de2021-04-09 10:43:12 +0000406func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) linkerAttributes {
Liz Kammer7a210ac2021-09-22 15:52:58 -0400407
Liz Kammer47535c52021-06-02 16:02:22 -0400408 var headerDeps bazel.LabelListAttribute
Liz Kammer7a210ac2021-09-22 15:52:58 -0400409 var implementationHeaderDeps bazel.LabelListAttribute
410 var deps bazel.LabelListAttribute
411 var implementationDeps bazel.LabelListAttribute
Rupert Shuttleworthc50fa8d2021-05-06 02:40:33 -0400412 var dynamicDeps bazel.LabelListAttribute
Liz Kammer7a210ac2021-09-22 15:52:58 -0400413 var implementationDynamicDeps bazel.LabelListAttribute
Chris Parsons08648312021-05-06 16:23:19 -0400414 var wholeArchiveDeps bazel.LabelListAttribute
Liz Kammer135bf552021-08-11 10:46:06 -0400415 systemSharedDeps := bazel.LabelListAttribute{ForceSpecifyEmptyList: true}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400416
Jingwen Chen63930982021-03-24 10:04:33 -0400417 var linkopts bazel.StringListAttribute
Lukacs T. Berki1353e592021-04-30 15:35:09 +0200418 var versionScript bazel.LabelAttribute
Jingwen Chen6ada5892021-09-17 11:38:09 +0000419 var linkCrt bazel.BoolAttribute
Liz Kammerd366c902021-06-03 13:43:01 -0400420 var useLibcrt bazel.BoolAttribute
Jingwen Chen63930982021-03-24 10:04:33 -0400421
Jingwen Chen3d383bb2021-06-09 07:18:37 +0000422 var stripKeepSymbols bazel.BoolAttribute
423 var stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
424 var stripKeepSymbolsList bazel.StringListAttribute
425 var stripAll bazel.BoolAttribute
426 var stripNone bazel.BoolAttribute
427
Jingwen Chen3d383bb2021-06-09 07:18:37 +0000428 for axis, configToProps := range module.GetArchVariantProperties(ctx, &StripProperties{}) {
429 for config, props := range configToProps {
430 if stripProperties, ok := props.(*StripProperties); ok {
431 stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols)
432 stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list)
433 stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame)
434 stripAll.SetSelectValue(axis, config, stripProperties.Strip.All)
435 stripNone.SetSelectValue(axis, config, stripProperties.Strip.None)
436 }
437 }
438 }
439
Jingwen Chen6ada5892021-09-17 11:38:09 +0000440 // Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
441 var disallowedArchVariantCrt bool
442
Liz Kammer9abd62d2021-05-21 08:37:59 -0400443 for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
444 for config, props := range configToProps {
445 if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
Liz Kammer7a210ac2021-09-22 15:52:58 -0400446
Liz Kammer135bf552021-08-11 10:46:06 -0400447 // Excludes to parallel Soong:
448 // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
Liz Kammer47535c52021-06-02 16:02:22 -0400449 staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
Liz Kammer7a210ac2021-09-22 15:52:58 -0400450 staticDeps := partitionExportedAndImplementationsDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
451 deps.SetSelectValue(axis, config, staticDeps.export)
452 implementationDeps.SetSelectValue(axis, config, staticDeps.implementation)
453
454 wholeStaticLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
455 wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, baseLinkerProps.Exclude_static_libs))
Chris Parsons51f8c392021-08-03 21:01:05 -0400456
Liz Kammer135bf552021-08-11 10:46:06 -0400457 systemSharedLibs := baseLinkerProps.System_shared_libs
458 // systemSharedLibs distinguishes between nil/empty list behavior:
459 // nil -> use default values
460 // empty list -> no values specified
461 if len(systemSharedLibs) > 0 {
462 systemSharedLibs = android.FirstUniqueStrings(systemSharedLibs)
Chris Parsons51f8c392021-08-03 21:01:05 -0400463 }
Chris Parsons953b3562021-09-20 15:14:39 -0400464 systemSharedDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
Chris Parsons51f8c392021-08-03 21:01:05 -0400465
466 sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
Liz Kammer7a210ac2021-09-22 15:52:58 -0400467 sharedDeps := partitionExportedAndImplementationsDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
468 dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
469 implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400470
Liz Kammer47535c52021-06-02 16:02:22 -0400471 headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
Liz Kammer7a210ac2021-09-22 15:52:58 -0400472 hDeps := partitionExportedAndImplementationsDeps(ctx, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps)
473
474 headerDeps.SetSelectValue(axis, config, hDeps.export)
475 implementationHeaderDeps.SetSelectValue(axis, config, hDeps.implementation)
Liz Kammer47535c52021-06-02 16:02:22 -0400476
477 linkopts.SetSelectValue(axis, config, getBp2BuildLinkerFlags(baseLinkerProps))
Rupert Shuttleworth22cd2eb2021-05-27 02:15:54 -0400478 if baseLinkerProps.Version_script != nil {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400479 versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
Rupert Shuttleworth22cd2eb2021-05-27 02:15:54 -0400480 }
Liz Kammerd366c902021-06-03 13:43:01 -0400481 useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt())
Jingwen Chen6ada5892021-09-17 11:38:09 +0000482
483 // it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
484 if baseLinkerProps.crt() != nil {
485 if axis == bazel.NoConfigAxis {
486 linkCrt.SetSelectValue(axis, config, baseLinkerProps.crt())
487 } else if axis == bazel.ArchConfigurationAxis {
488 disallowedArchVariantCrt = true
489 }
490 }
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400491 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400492 }
493 }
494
Jingwen Chen6ada5892021-09-17 11:38:09 +0000495 if disallowedArchVariantCrt {
496 ctx.ModuleErrorf("nocrt is not supported for arch variants")
497 }
498
Liz Kammer47535c52021-06-02 16:02:22 -0400499 type productVarDep struct {
500 // the name of the corresponding excludes field, if one exists
501 excludesField string
502 // reference to the bazel attribute that should be set for the given product variable config
503 attribute *bazel.LabelListAttribute
Liz Kammer2d7bbe32021-06-10 18:20:06 -0400504
Chris Parsons953b3562021-09-20 15:14:39 -0400505 depResolutionFunc func(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList
Liz Kammer47535c52021-06-02 16:02:22 -0400506 }
507
508 productVarToDepFields := map[string]productVarDep{
509 // product variables do not support exclude_shared_libs
Liz Kammer7a210ac2021-09-22 15:52:58 -0400510 "Shared_libs": productVarDep{attribute: &implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
511 "Static_libs": productVarDep{"Exclude_static_libs", &implementationDeps, bazelLabelForStaticDepsExcludes},
Chris Parsons953b3562021-09-20 15:14:39 -0400512 "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
Liz Kammer47535c52021-06-02 16:02:22 -0400513 }
514
515 productVariableProps := android.ProductVariableProperties(ctx)
516 for name, dep := range productVarToDepFields {
517 props, exists := productVariableProps[name]
518 excludeProps, excludesExists := productVariableProps[dep.excludesField]
519 // if neither an include or excludes property exists, then skip it
520 if !exists && !excludesExists {
521 continue
522 }
523 // collect all the configurations that an include or exclude property exists for.
524 // we want to iterate all configurations rather than either the include or exclude because for a
525 // particular configuration we may have only and include or only an exclude to handle
526 configs := make(map[string]bool, len(props)+len(excludeProps))
527 for config := range props {
528 configs[config] = true
529 }
530 for config := range excludeProps {
531 configs[config] = true
532 }
533
534 for config := range configs {
535 prop, includesExists := props[config]
536 excludesProp, excludesExists := excludeProps[config]
537 var includes, excludes []string
538 var ok bool
539 // if there was no includes/excludes property, casting fails and that's expected
540 if includes, ok = prop.Property.([]string); includesExists && !ok {
541 ctx.ModuleErrorf("Could not convert product variable %s property", name)
542 }
543 if excludes, ok = excludesProp.Property.([]string); excludesExists && !ok {
544 ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField)
545 }
Liz Kammer2d7bbe32021-06-10 18:20:06 -0400546
547 dep.attribute.SetSelectValue(bazel.ProductVariableConfigurationAxis(config), config, dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes))
Liz Kammer47535c52021-06-02 16:02:22 -0400548 }
549 }
550
Liz Kammer7a210ac2021-09-22 15:52:58 -0400551 headerDeps.Append(deps)
552 implementationHeaderDeps.Append(implementationDeps)
553
554 headerDeps.ResolveExcludes()
555 implementationHeaderDeps.ResolveExcludes()
Liz Kammer47535c52021-06-02 16:02:22 -0400556 dynamicDeps.ResolveExcludes()
Liz Kammer7a210ac2021-09-22 15:52:58 -0400557 implementationDynamicDeps.ResolveExcludes()
Liz Kammer47535c52021-06-02 16:02:22 -0400558 wholeArchiveDeps.ResolveExcludes()
559
Jingwen Chen107c0de2021-04-09 10:43:12 +0000560 return linkerAttributes{
Liz Kammer7a210ac2021-09-22 15:52:58 -0400561 deps: headerDeps,
562 implementationDeps: implementationHeaderDeps,
563 dynamicDeps: dynamicDeps,
564 implementationDynamicDeps: implementationDynamicDeps,
565 wholeArchiveDeps: wholeArchiveDeps,
566 systemDynamicDeps: systemSharedDeps,
567
Jingwen Chen6ada5892021-09-17 11:38:09 +0000568 linkCrt: linkCrt,
Liz Kammer7a210ac2021-09-22 15:52:58 -0400569 linkopts: linkopts,
570 useLibcrt: useLibcrt,
571 versionScript: versionScript,
Jingwen Chen3d383bb2021-06-09 07:18:37 +0000572
573 // Strip properties
574 stripKeepSymbols: stripKeepSymbols,
575 stripKeepSymbolsAndDebugFrame: stripKeepSymbolsAndDebugFrame,
576 stripKeepSymbolsList: stripKeepSymbolsList,
577 stripAll: stripAll,
578 stripNone: stripNone,
Jingwen Chen107c0de2021-04-09 10:43:12 +0000579 }
Jingwen Chen91220d72021-03-24 02:18:33 -0400580}
581
Jingwen Chened9c17d2021-04-13 07:14:55 +0000582// Relativize a list of root-relative paths with respect to the module's
583// directory.
584//
585// include_dirs Soong prop are root-relative (b/183742505), but
586// local_include_dirs, export_include_dirs and export_system_include_dirs are
587// module dir relative. This function makes a list of paths entirely module dir
588// relative.
589//
590// For the `include` attribute, Bazel wants the paths to be relative to the
591// module.
592func bp2BuildMakePathsRelativeToModule(ctx android.BazelConversionPathContext, paths []string) []string {
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000593 var relativePaths []string
594 for _, path := range paths {
Jingwen Chened9c17d2021-04-13 07:14:55 +0000595 // Semantics of filepath.Rel: join(ModuleDir, rel(ModuleDir, path)) == path
596 relativePath, err := filepath.Rel(ctx.ModuleDir(), path)
597 if err != nil {
598 panic(err)
599 }
Rupert Shuttleworthb8151682021-04-06 20:06:21 +0000600 relativePaths = append(relativePaths, relativePath)
601 }
602 return relativePaths
603}
604
Liz Kammer5fad5012021-09-09 14:08:21 -0400605// BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel
606// attributes.
607type BazelIncludes struct {
608 Includes bazel.StringListAttribute
609 SystemIncludes bazel.StringListAttribute
610}
611
612func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
Jingwen Chen91220d72021-03-24 02:18:33 -0400613 libraryDecorator := module.linker.(*libraryDecorator)
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400614 return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
615}
Jingwen Chen91220d72021-03-24 02:18:33 -0400616
Liz Kammer5fad5012021-09-09 14:08:21 -0400617// Bp2buildParseExportedIncludesForPrebuiltLibrary returns a BazelIncludes with Bazel-ified values
618// to export includes from the underlying module's properties.
619func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
Rupert Shuttleworthffd45822021-05-14 03:02:34 -0400620 prebuiltLibraryLinker := module.linker.(*prebuiltLibraryLinker)
621 libraryDecorator := prebuiltLibraryLinker.libraryDecorator
622 return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
623}
624
625// bp2BuildParseExportedIncludes creates a string list attribute contains the
626// exported included directories of a module.
Liz Kammer5fad5012021-09-09 14:08:21 -0400627func bp2BuildParseExportedIncludesHelper(ctx android.TopDownMutatorContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes {
628 exported := BazelIncludes{}
Liz Kammer9abd62d2021-05-21 08:37:59 -0400629 for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
630 for config, props := range configToProps {
631 if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
Liz Kammer5fad5012021-09-09 14:08:21 -0400632 if len(flagExporterProperties.Export_include_dirs) > 0 {
633 exported.Includes.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs)
634 }
635 if len(flagExporterProperties.Export_system_include_dirs) > 0 {
636 exported.SystemIncludes.SetSelectValue(axis, config, flagExporterProperties.Export_system_include_dirs)
Rupert Shuttleworthc194ffb2021-05-19 06:49:02 -0400637 }
Rupert Shuttleworth375451e2021-04-26 07:49:08 -0400638 }
Rupert Shuttleworth375451e2021-04-26 07:49:08 -0400639 }
640 }
Liz Kammer5fad5012021-09-09 14:08:21 -0400641 exported.Includes.DeduplicateAxesFromBase()
642 exported.SystemIncludes.DeduplicateAxesFromBase()
Rupert Shuttleworth375451e2021-04-26 07:49:08 -0400643
Liz Kammer5fad5012021-09-09 14:08:21 -0400644 return exported
Jingwen Chen91220d72021-03-24 02:18:33 -0400645}
Chris Parsons953b3562021-09-20 15:14:39 -0400646
647func bazelLabelForStaticModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
648 label := android.BazelModuleLabel(ctx, m)
649 if aModule, ok := m.(android.Module); ok {
650 if ctx.OtherModuleType(aModule) == "cc_library" && !android.GenerateCcLibraryStaticOnly(m.Name()) {
651 label += "_bp2build_cc_library_static"
652 }
653 }
654 return label
655}
656
657func bazelLabelForSharedModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
658 // cc_library, at it's root name, propagates the shared library, which depends on the static
659 // library.
660 return android.BazelModuleLabel(ctx, m)
661}
662
663func bazelLabelForStaticWholeModuleDeps(ctx android.TopDownMutatorContext, m blueprint.Module) string {
664 label := bazelLabelForStaticModule(ctx, m)
665 if aModule, ok := m.(android.Module); ok {
666 if android.IsModulePrebuilt(aModule) {
667 label += "_alwayslink"
668 }
669 }
670 return label
671}
672
673func bazelLabelForWholeDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
674 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps)
675}
676
677func bazelLabelForWholeDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
678 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps)
679}
680
681func bazelLabelForStaticDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
682 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule)
683}
684
685func bazelLabelForStaticDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
686 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule)
687}
688
689func bazelLabelForSharedDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
690 return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule)
691}
692
693func bazelLabelForHeaderDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
694 // This is not elegant, but bp2build's shared library targets only propagate
695 // their header information as part of the normal C++ provider.
696 return bazelLabelForSharedDeps(ctx, modules)
697}
698
699func bazelLabelForSharedDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
700 return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
701}