diff options
Diffstat (limited to 'cc')
| -rw-r--r-- | cc/androidmk.go | 7 | ||||
| -rw-r--r-- | cc/binary.go | 57 | ||||
| -rw-r--r-- | cc/bp2build.go | 208 | ||||
| -rw-r--r-- | cc/builder.go | 32 | ||||
| -rw-r--r-- | cc/cc.go | 100 | ||||
| -rw-r--r-- | cc/compiler.go | 33 | ||||
| -rw-r--r-- | cc/config/darwin_host.go | 7 | ||||
| -rw-r--r-- | cc/config/global.go | 4 | ||||
| -rw-r--r-- | cc/fuzz.go | 6 | ||||
| -rw-r--r-- | cc/libbuildversion/Android.bp | 2 | ||||
| -rw-r--r-- | cc/libbuildversion/libbuildversion.cpp | 4 | ||||
| -rw-r--r-- | cc/library.go | 316 | ||||
| -rw-r--r-- | cc/library_headers.go | 48 | ||||
| -rw-r--r-- | cc/library_headers_test.go | 105 | ||||
| -rw-r--r-- | cc/library_test.go | 26 | ||||
| -rw-r--r-- | cc/linkable.go | 4 | ||||
| -rw-r--r-- | cc/ndk_sysroot.go | 16 | ||||
| -rw-r--r-- | cc/object.go | 16 | ||||
| -rw-r--r-- | cc/pgo.go | 8 | ||||
| -rw-r--r-- | cc/prebuilt.go | 73 | ||||
| -rw-r--r-- | cc/proto.go | 76 | ||||
| -rw-r--r-- | cc/sanitize.go | 4 | ||||
| -rw-r--r-- | cc/test.go | 21 | ||||
| -rw-r--r-- | cc/tidy.go | 152 |
24 files changed, 925 insertions, 400 deletions
diff --git a/cc/androidmk.go b/cc/androidmk.go index 45bb1ca2a..636bab81e 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -263,9 +263,10 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries library.androidMkWriteExportedFlags(entries) library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries) - _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base()) - - entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext) + if entries.OutputFile.Valid() { + _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base()) + entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext) + } if library.coverageOutputFile.Valid() { entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputFile.String()) diff --git a/cc/binary.go b/cc/binary.go index a5afb0725..50175d92f 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -18,6 +18,7 @@ import ( "path/filepath" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" "android/soong/bazel" @@ -68,13 +69,14 @@ func RegisterBinaryBuildComponents(ctx android.RegistrationContext) { // cc_binary produces a binary that is runnable on a device. func BinaryFactory() android.Module { - module, _ := NewBinary(android.HostAndDeviceSupported) + module, _ := newBinary(android.HostAndDeviceSupported, true) return module.Init() } // cc_binary_host produces a binary that is runnable on a host. func BinaryHostFactory() android.Module { - module, _ := NewBinary(android.HostSupported) + module, _ := newBinary(android.HostSupported, true) + module.bazelable = true return module.Init() } @@ -192,6 +194,10 @@ func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { // Individual module implementations which comprise a C++ binary should call this function, // set some fields on the result, and then call the Init function. func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { + return newBinary(hod, true) +} + +func newBinary(hod android.HostOrDeviceSupported, bazelable bool) (*Module, *binaryDecorator) { module := newModule(hod, android.MultilibFirst) binary := &binaryDecorator{ baseLinker: NewBaseLinker(module.sanitize), @@ -200,6 +206,7 @@ func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { module.compiler = NewBaseCompiler() module.linker = binary module.installer = binary + module.bazelable = bazelable // Allow module to be added as member of an sdk/module_exports. module.sdkMemberTypes = []android.SdkMemberType{ @@ -344,6 +351,12 @@ func (binary *binaryDecorator) link(ctx ModuleContext, flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-dynamic-linker") } + if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() { + fatOutputFile := outputFile + outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName) + transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path()) + } + builderFlags := flagsToBuilderFlags(flags) stripFlags := flagsToStripFlags(flags) if binary.stripper.NeedsStrip(ctx) { @@ -388,7 +401,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext, } } - var validations android.WritablePaths + var validations android.Paths // Handle host bionic linker symbols. if ctx.Os() == android.LinuxBionic && !binary.static() { @@ -411,6 +424,7 @@ func (binary *binaryDecorator) link(ctx ModuleContext, linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...) linkerDeps = append(linkerDeps, deps.SharedLibsDeps...) linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...) + linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...) } validations = append(validations, objs.tidyFiles...) @@ -543,33 +557,7 @@ func (binary *binaryDecorator) verifyHostBionicLinker(ctx ModuleContext, in, lin }) } -func init() { - android.RegisterBp2BuildMutator("cc_binary", BinaryBp2build) - android.RegisterBp2BuildMutator("cc_binary_host", BinaryHostBp2build) -} - -func BinaryBp2build(ctx android.TopDownMutatorContext) { - binaryBp2build(ctx, "cc_binary") -} - -func BinaryHostBp2build(ctx android.TopDownMutatorContext) { - binaryBp2build(ctx, "cc_binary_host") -} - -func binaryBp2build(ctx android.TopDownMutatorContext, typ string) { - m, ok := ctx.Module().(*Module) - if !ok { - // Not a cc module - return - } - if !m.ConvertWithBp2build(ctx) { - return - } - - if ctx.ModuleType() != typ { - return - } - +func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { var compatibleWith bazel.StringListAttribute if typ == "cc_binary_host" { //incompatible with android OS @@ -578,9 +566,16 @@ func binaryBp2build(ctx android.TopDownMutatorContext, typ string) { } baseAttrs := bp2BuildParseBaseProps(ctx, m) + binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) + + if proptools.BoolDefault(binaryLinkerAttrs.Linkshared, true) { + baseAttrs.implementationDynamicDeps.Add(baseAttrs.protoDependency) + } else { + baseAttrs.implementationDeps.Add(baseAttrs.protoDependency) + } attrs := &binaryAttributes{ - binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m), + binaryLinkerAttrs: binaryLinkerAttrs, Srcs: baseAttrs.srcs, Srcs_c: baseAttrs.cSrcs, diff --git a/cc/bp2build.go b/cc/bp2build.go index d9494362f..6c1646cbb 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -27,9 +27,10 @@ import ( ) const ( - cSrcPartition = "c" - asSrcPartition = "as" - cppSrcPartition = "cpp" + cSrcPartition = "c" + asSrcPartition = "as" + cppSrcPartition = "cpp" + protoSrcPartition = "proto" ) // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- @@ -41,52 +42,53 @@ type staticOrSharedAttributes struct { Hdrs bazel.LabelListAttribute Copts bazel.StringListAttribute - Deps bazel.LabelListAttribute - Implementation_deps bazel.LabelListAttribute - Dynamic_deps bazel.LabelListAttribute - Implementation_dynamic_deps bazel.LabelListAttribute - Whole_archive_deps bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Implementation_deps bazel.LabelListAttribute + Dynamic_deps bazel.LabelListAttribute + Implementation_dynamic_deps bazel.LabelListAttribute + Whole_archive_deps bazel.LabelListAttribute + Implementation_whole_archive_deps bazel.LabelListAttribute System_dynamic_deps bazel.LabelListAttribute } func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { - // Check that a module is a filegroup type named <label>. - isFilegroupNamed := func(m android.Module, fullLabel string) bool { - if ctx.OtherModuleType(m) != "filegroup" { - return false - } - labelParts := strings.Split(fullLabel, ":") - if len(labelParts) > 2 { - // There should not be more than one colon in a label. - ctx.ModuleErrorf("%s is not a valid Bazel label for a filegroup", fullLabel) - } - return m.Name() == labelParts[len(labelParts)-1] + // Check that a module is a filegroup type + isFilegroup := func(m blueprint.Module) bool { + return ctx.OtherModuleType(m) == "filegroup" } // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl // macro. addSuffixForFilegroup := func(suffix string) bazel.LabelMapper { - return func(ctx bazel.OtherModuleContext, label string) (string, bool) { - m, exists := ctx.ModuleFromName(label) - if !exists { - return label, false - } - aModule, _ := m.(android.Module) - if !isFilegroupNamed(aModule, label) { - return label, false + return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + m, exists := ctx.ModuleFromName(label.OriginalModuleName) + labelStr := label.Label + if !exists || !isFilegroup(m) { + return labelStr, false } - return label + suffix, true + return labelStr + suffix, true } } + isProtoFilegroup := func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + m, exists := ctx.ModuleFromName(label.OriginalModuleName) + labelStr := label.Label + if !exists || !isFilegroup(m) { + return labelStr, false + } + likelyProtos := strings.HasSuffix(labelStr, "proto") || strings.HasSuffix(labelStr, "protos") + return labelStr, likelyProtos + } + // TODO(b/190006308): Handle language detection of sources in a Bazel rule. partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, // C++ is the "catch-all" group, and comprises generated sources because we don't // know the language of these sources until the genrule is executed. - cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, + cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, + protoSrcPartition: bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup}, }) return partitioned @@ -195,6 +197,11 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo attrs.Srcs_c = partitionedSrcs[cSrcPartition] attrs.Srcs_as = partitionedSrcs[asSrcPartition] + if !partitionedSrcs[protoSrcPartition].IsEmpty() { + // TODO(b/208815215): determine whether this is used and add support if necessary + ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported") + } + return attrs } @@ -230,6 +237,8 @@ func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, m type baseAttributes struct { compilerAttributes linkerAttributes + + protoDependency *bazel.LabelAttribute } // Convenience struct to hold all attributes parsed from compiler properties. @@ -252,10 +261,15 @@ type compilerAttributes struct { // Not affected by arch variants stl *string + cStd *string cppStd *string localIncludes bazel.StringListAttribute absoluteIncludes bazel.StringListAttribute + + includes BazelIncludes + + protoSrcs bazel.LabelListAttribute } func parseCommandLineFlags(soongFlags []string) []string { @@ -278,8 +292,7 @@ func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversi localIncludeDirs := props.Local_include_dirs if axis == bazel.NoConfigAxis { - ca.cppStd = bp2buildResolveCppStdValue(props.Cpp_std, props.Gnu_extensions) - + ca.cStd, ca.cppStd = bp2buildResolveCppStdValue(props.C_std, props.Cpp_std, props.Gnu_extensions) if includeBuildDirectory(props.Include_build_directory) { localIncludeDirs = append(localIncludeDirs, ".") } @@ -337,6 +350,8 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i ca.srcs.ResolveExcludes() partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs) + ca.protoSrcs = partitionedSrcs[protoSrcPartition] + for p, lla := range partitionedSrcs { // if there are no sources, there is no need for headers if lla.IsEmpty() { @@ -371,28 +386,63 @@ func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProper return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs } -func bp2buildResolveCppStdValue(cpp_std *string, gnu_extensions *bool) *string { - var cppStd *string - // If cpp_std is not specified, don't generate it in the - // BUILD file. For readability purposes, cpp_std and gnu_extensions are - // combined into a single -std=<version> copt, except in the - // default case where cpp_std is nil and gnu_extensions is true or unspecified, - // then the toolchain's default "gnu++17" will be used. +func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions *bool) (*string, *string) { + var cStdVal, cppStdVal string + // If c{,pp}std properties are not specified, don't generate them in the BUILD file. + // Defaults are handled by the toolchain definition. + // However, if gnu_extensions is false, then the default gnu-to-c version must be specified. if cpp_std != nil { - // TODO(b/202491296): Handle C_std. - // These transformations are shared with compiler.go. - cppStdVal := parseCppStd(cpp_std) - _, cppStdVal = maybeReplaceGnuToC(gnu_extensions, "", cppStdVal) - cppStd = &cppStdVal + cppStdVal = parseCppStd(cpp_std) } else if gnu_extensions != nil && !*gnu_extensions { - cppStdVal := "c++17" - cppStd = &cppStdVal + cppStdVal = "c++17" + } + if c_std != nil { + cStdVal = parseCStd(c_std) + } else if gnu_extensions != nil && !*gnu_extensions { + cStdVal = "c99" + } + + cStdVal, cppStdVal = maybeReplaceGnuToC(gnu_extensions, cStdVal, cppStdVal) + var c_std_prop, cpp_std_prop *string + if cStdVal != "" { + c_std_prop = &cStdVal + } + if cppStdVal != "" { + cpp_std_prop = &cppStdVal } - return cppStd + + return c_std_prop, cpp_std_prop +} + +// packageFromLabel extracts package from a fully-qualified or relative Label and whether the label +// is fully-qualified. +// e.g. fully-qualified "//a/b:foo" -> "a/b", true, relative: ":bar" -> ".", false +func packageFromLabel(label string) (string, bool) { + split := strings.Split(label, ":") + if len(split) != 2 { + return "", false + } + if split[0] == "" { + return ".", false + } + // remove leading "//" + return split[0][2:], true +} + +// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList> +func includesFromLabelList(labelList bazel.LabelList) (relative, absolute []string) { + for _, hdr := range labelList.Includes { + if pkg, hasPkg := packageFromLabel(hdr.Label); hasPkg { + absolute = append(absolute, pkg) + } else if pkg != "" { + relative = append(relative, pkg) + } + } + return relative, absolute } // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes. -func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Module) baseAttributes { +func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes { archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) @@ -434,6 +484,18 @@ func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Modu headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportHdrs, android.BazelLabelForModuleDeps) implementationHdrs.SetSelectValue(axis, config, headers.implementation) compilerAttrs.hdrs.SetSelectValue(axis, config, headers.export) + + exportIncludes, exportAbsoluteIncludes := includesFromLabelList(headers.export) + compilerAttrs.includes.Includes.SetSelectValue(axis, config, exportIncludes) + compilerAttrs.includes.AbsoluteIncludes.SetSelectValue(axis, config, exportAbsoluteIncludes) + + includes, absoluteIncludes := includesFromLabelList(headers.implementation) + currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, config) + currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...)) + compilerAttrs.absoluteIncludes.SetSelectValue(axis, config, currAbsoluteIncludes) + currIncludes := compilerAttrs.localIncludes.SelectValue(axis, config) + currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...)) + compilerAttrs.localIncludes.SetSelectValue(axis, config, currIncludes) } } @@ -448,23 +510,34 @@ func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Modu (&compilerAttrs).finalize(ctx, implementationHdrs) (&linkerAttrs).finalize() + protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs) + + // bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know + // which. This will add the newly generated proto library to the appropriate attribute and nothing + // to the other + (&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib) + (&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib) + return baseAttributes{ compilerAttrs, linkerAttrs, + protoDep.protoDep, } } // Convenience struct to hold all attributes parsed from linker properties. type linkerAttributes struct { - deps bazel.LabelListAttribute - implementationDeps bazel.LabelListAttribute - dynamicDeps bazel.LabelListAttribute - implementationDynamicDeps bazel.LabelListAttribute - wholeArchiveDeps bazel.LabelListAttribute - systemDynamicDeps bazel.LabelListAttribute + deps bazel.LabelListAttribute + implementationDeps bazel.LabelListAttribute + dynamicDeps bazel.LabelListAttribute + implementationDynamicDeps bazel.LabelListAttribute + wholeArchiveDeps bazel.LabelListAttribute + implementationWholeArchiveDeps bazel.LabelListAttribute + systemDynamicDeps bazel.LabelListAttribute linkCrt bazel.BoolAttribute useLibcrt bazel.BoolAttribute + useVersionLib bazel.BoolAttribute linkopts bazel.StringListAttribute additionalLinkerInputs bazel.LabelListAttribute stripKeepSymbols bazel.BoolAttribute @@ -534,6 +607,10 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion la.linkopts.SetSelectValue(axis, config, linkerFlags) la.useLibcrt.SetSelectValue(axis, config, props.libCrt()) + if axis == bazel.NoConfigAxis { + la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib) + } + // it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it. if props.crt() != nil { if axis == bazel.NoConfigAxis { @@ -656,13 +733,14 @@ func bp2BuildMakePathsRelativeToModule(ctx android.BazelConversionPathContext, p // BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel // attributes. type BazelIncludes struct { - Includes bazel.StringListAttribute - SystemIncludes bazel.StringListAttribute + AbsoluteIncludes bazel.StringListAttribute + Includes bazel.StringListAttribute + SystemIncludes bazel.StringListAttribute } -func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module) BazelIncludes { +func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module, existingIncludes BazelIncludes) BazelIncludes { libraryDecorator := module.linker.(*libraryDecorator) - return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator) + return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator, &existingIncludes) } // Bp2buildParseExportedIncludesForPrebuiltLibrary returns a BazelIncludes with Bazel-ified values @@ -670,25 +748,31 @@ func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, modul func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.BazelConversionPathContext, module *Module) BazelIncludes { prebuiltLibraryLinker := module.linker.(*prebuiltLibraryLinker) libraryDecorator := prebuiltLibraryLinker.libraryDecorator - return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator) + return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator, nil) } // bp2BuildParseExportedIncludes creates a string list attribute contains the // exported included directories of a module. -func bp2BuildParseExportedIncludesHelper(ctx android.BazelConversionPathContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes { - exported := BazelIncludes{} +func bp2BuildParseExportedIncludesHelper(ctx android.BazelConversionPathContext, module *Module, libraryDecorator *libraryDecorator, includes *BazelIncludes) BazelIncludes { + var exported BazelIncludes + if includes != nil { + exported = *includes + } else { + exported = BazelIncludes{} + } for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) { for config, props := range configToProps { if flagExporterProperties, ok := props.(*FlagExporterProperties); ok { if len(flagExporterProperties.Export_include_dirs) > 0 { - exported.Includes.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs) + exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...))) } if len(flagExporterProperties.Export_system_include_dirs) > 0 { - exported.SystemIncludes.SetSelectValue(axis, config, flagExporterProperties.Export_system_include_dirs) + exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...))) } } } } + exported.AbsoluteIncludes.DeduplicateAxesFromBase() exported.Includes.DeduplicateAxesFromBase() exported.SystemIncludes.DeduplicateAxesFromBase() diff --git a/cc/builder.go b/cc/builder.go index 72c2fa555..8af225535 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -165,6 +165,12 @@ var ( } }() + darwinLipo = pctx.AndroidStaticRule("darwinLipo", + blueprint.RuleParams{ + Command: "${config.MacLipoPath} -create -output $out $in", + CommandDeps: []string{"${config.MacLipoPath}"}, + }) + _ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh") // Rule to repack an archive (.a) file with a subset of object files. @@ -413,7 +419,7 @@ type StripFlags struct { // Objects is a collection of file paths corresponding to outputs for C++ related build statements. type Objects struct { objFiles android.Paths - tidyFiles android.WritablePaths + tidyFiles android.Paths coverageFiles android.Paths sAbiDumpFiles android.Paths kytheFiles android.Paths @@ -422,7 +428,7 @@ type Objects struct { func (a Objects) Copy() Objects { return Objects{ objFiles: append(android.Paths{}, a.objFiles...), - tidyFiles: append(android.WritablePaths{}, a.tidyFiles...), + tidyFiles: append(android.Paths{}, a.tidyFiles...), coverageFiles: append(android.Paths{}, a.coverageFiles...), sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...), kytheFiles: append(android.Paths{}, a.kytheFiles...), @@ -451,11 +457,11 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no // Source files are one-to-one with tidy, coverage, or kythe files, if enabled. objFiles := make(android.Paths, len(srcFiles)) - var tidyFiles android.WritablePaths + var tidyFiles android.Paths noTidySrcsMap := make(map[android.Path]bool) var tidyVars string if flags.tidy { - tidyFiles = make(android.WritablePaths, 0, len(srcFiles)) + tidyFiles = make(android.Paths, 0, len(srcFiles)) for _, path := range noTidySrcs { noTidySrcsMap[path] = true } @@ -665,7 +671,6 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no rule = clangTidyRE } - ctx.TidyFile(tidyFile) ctx.Build(pctx, android.BuildParams{ Rule: rule, Description: "clang-tidy " + srcFile.Rel(), @@ -719,7 +724,7 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no // Generate a rule for compiling multiple .o files to a static library (.a) func transformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths, wholeStaticLibs android.Paths, - flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.WritablePaths) { + flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) { arCmd := "${config.ClangBin}/llvm-ar" arFlags := "" @@ -734,7 +739,7 @@ func transformObjToStaticLib(ctx android.ModuleContext, Output: outputFile, Inputs: objFiles, Implicits: deps, - Validations: validations.Paths(), + Validations: validations, Args: map[string]string{ "arFlags": "crsPD" + arFlags, "arCmd": arCmd, @@ -764,7 +769,7 @@ func transformObjToStaticLib(ctx android.ModuleContext, func transformObjToDynamicBinary(ctx android.ModuleContext, objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths, groupLate bool, flags builderFlags, outputFile android.WritablePath, - implicitOutputs android.WritablePaths, validations android.WritablePaths) { + implicitOutputs android.WritablePaths, validations android.Paths) { ldCmd := "${config.ClangBin}/clang++" @@ -831,7 +836,7 @@ func transformObjToDynamicBinary(ctx android.ModuleContext, Inputs: objFiles, Implicits: deps, OrderOnly: sharedLibs, - Validations: validations.Paths(), + Validations: validations, Args: args, }) } @@ -1060,6 +1065,15 @@ func transformDarwinStrip(ctx android.ModuleContext, inputFile android.Path, }) } +func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) { + ctx.Build(pctx, android.BuildParams{ + Rule: darwinLipo, + Description: "lipo " + outputFile.Base(), + Output: outputFile, + Inputs: inputFiles, + }) +} + // Registers build statement to zip one or more coverage files. func transformCoverageFilesToZip(ctx android.ModuleContext, inputs Objects, baseName string) android.OptionalPath { @@ -167,6 +167,10 @@ type PathDeps struct { // Path to the dynamic linker binary DynamicLinker android.OptionalPath + + // For Darwin builds, the path to the second architecture's output that should + // be combined with this architectures's output into a FAT MachO file. + DarwinSecondArchOutput android.OptionalPath } // LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module @@ -682,6 +686,15 @@ func (d libraryDependencyTag) static() bool { return d.Kind == staticLibraryDependency } +func (d libraryDependencyTag) LicenseAnnotations() []android.LicenseAnnotation { + if d.shared() { + return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency} + } + return nil +} + +var _ android.LicenseAnnotationsDependencyTag = libraryDependencyTag{} + // InstallDepNeeded returns true for shared libraries so that shared library dependencies of // binaries or other shared libraries are installed as dependencies. func (d libraryDependencyTag) InstallDepNeeded() bool { @@ -773,8 +786,9 @@ type Module struct { Properties BaseProperties // initialize before calling Init - hod android.HostOrDeviceSupported - multilib android.Multilib + hod android.HostOrDeviceSupported + multilib android.Multilib + bazelable bool // Allowable SdkMemberTypes of this module type. sdkMemberTypes []android.SdkMemberType @@ -815,6 +829,10 @@ type Module struct { makeLinkType string // Kythe (source file indexer) paths for this compilation module kytheFiles android.Paths + // Object .o file output paths for this compilation module + objFiles android.Paths + // Tidy .tidy file output paths for this compilation module + tidyFiles android.Paths // For apex variants, this is set as apex.min_sdk_version apexSdkVersion android.ApiLevel @@ -1133,7 +1151,9 @@ func (c *Module) Init() android.Module { } android.InitAndroidArchModule(c, c.hod, c.multilib) - android.InitBazelModule(c) + if c.bazelable { + android.InitBazelModule(c) + } android.InitApexModule(c) android.InitSdkAwareModule(c) android.InitDefaultableModule(c) @@ -1713,7 +1733,15 @@ func (c *Module) setSubnameProperty(actx android.ModuleContext) { // Returns true if Bazel was successfully used for the analysis of this module. func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool { - bazelModuleLabel := c.GetBazelLabel(actx, c) + var bazelModuleLabel string + if actx.ModuleType() == "cc_library" && c.static() { + // cc_library is a special case in bp2build; two targets are generated -- one for each + // of the shared and static variants. The shared variant keeps the module name, but the + // static variant uses a different suffixed name. + bazelModuleLabel = bazelLabelForStaticModule(actx, c) + } else { + bazelModuleLabel = c.GetBazelLabel(actx, c) + } bazelActionsUsed := false // Mixed builds mode is disabled for modules outside of device OS. // TODO(b/200841190): Support non-device OS in mixed builds. @@ -1827,6 +1855,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { return } c.kytheFiles = objs.kytheFiles + c.objFiles = objs.objFiles + c.tidyFiles = objs.tidyFiles } if c.linker != nil { @@ -2570,6 +2600,11 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depName := ctx.OtherModuleName(dep) depTag := ctx.OtherModuleDependencyTag(dep) + if depTag == android.DarwinUniversalVariantTag { + depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile() + return + } + ccDep, ok := dep.(LinkableInterface) if !ok { @@ -3153,6 +3188,24 @@ func (c *Module) testBinary() bool { return false } +func (c *Module) benchmarkBinary() bool { + if b, ok := c.linker.(interface { + benchmarkBinary() bool + }); ok { + return b.benchmarkBinary() + } + return false +} + +func (c *Module) fuzzBinary() bool { + if f, ok := c.linker.(interface { + fuzzBinary() bool + }); ok { + return f.fuzzBinary() + } + return false +} + // Header returns true if the module is a header-only variant. (See cc/library.go header()). func (c *Module) Header() bool { if h, ok := c.linker.(interface { @@ -3398,6 +3451,45 @@ func (c *Module) AlwaysRequiresPlatformApexVariant() bool { var _ snapshot.RelativeInstallPath = (*Module)(nil) +// ConvertWithBp2build converts Module to Bazel for bp2build. +func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { + prebuilt := c.IsPrebuilt() + if c.Binary() { + if !prebuilt { + binaryBp2build(ctx, c, ctx.ModuleType()) + } + } else if c.Object() { + if !prebuilt { + objectBp2Build(ctx, c) + } + } else if c.CcLibrary() { + static := c.BuildStaticVariant() + shared := c.BuildSharedVariant() + + if static && shared { + if !prebuilt { + libraryBp2Build(ctx, c) + } + } else if !static && !shared { + if !prebuilt { + libraryHeadersBp2Build(ctx, c) + } + } else if static { + if prebuilt { + prebuiltLibraryStaticBp2Build(ctx, c) + } else { + sharedOrStaticLibraryBp2Build(ctx, c, true) + } + } else if shared { + if prebuilt { + prebuiltLibrarySharedBp2Build(ctx, c) + } else { + sharedOrStaticLibraryBp2Build(ctx, c, false) + } + } + } +} + // // Defaults // diff --git a/cc/compiler.go b/cc/compiler.go index ffe8b2e36..8adc3ab16 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -304,11 +304,24 @@ func parseCppStd(cppStdPtr *string) string { cppStd := String(cppStdPtr) switch cppStd { case "": - cppStd = config.CppStdVersion + return config.CppStdVersion case "experimental": - cppStd = config.ExperimentalCppStdVersion + return config.ExperimentalCppStdVersion + default: + return cppStd + } +} + +func parseCStd(cStdPtr *string) string { + cStd := String(cStdPtr) + switch cStd { + case "": + return config.CStdVersion + case "experimental": + return config.ExperimentalCStdVersion + default: + return cStd } - return cppStd } // Create a Flags struct that collects the compile flags from global values, @@ -479,13 +492,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags()) - cStd := config.CStdVersion - if String(compiler.Properties.C_std) == "experimental" { - cStd = config.ExperimentalCStdVersion - } else if String(compiler.Properties.C_std) != "" { - cStd = String(compiler.Properties.C_std) - } - + cStd := parseCStd(compiler.Properties.C_std) cppStd := parseCppStd(compiler.Properties.Cpp_std) cStd, cppStd = maybeReplaceGnuToC(compiler.Properties.Gnu_extensions, cStd, cppStd) @@ -630,9 +637,9 @@ var gnuToCReplacer = strings.NewReplacer("gnu", "c") func ndkPathDeps(ctx ModuleContext) android.Paths { if ctx.Module().(*Module).IsSdkVariant() { - // The NDK sysroot timestamp file depends on all the NDK sysroot files - // (headers and libraries). - return android.Paths{getNdkBaseTimestampFile(ctx)} + // The NDK sysroot timestamp file depends on all the NDK sysroot header files + // for compiling src to obj files. + return android.Paths{getNdkHeadersTimestampFile(ctx)} } return nil } diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go index 318acb4e7..206bec110 100644 --- a/cc/config/darwin_host.go +++ b/cc/config/darwin_host.go @@ -54,6 +54,7 @@ var ( darwinSupportedSdkVersions = []string{ "11", + "12", } darwinAvailableLibraries = append( @@ -87,6 +88,10 @@ func init() { return getMacTools(ctx).arPath }) + pctx.VariableFunc("MacLipoPath", func(ctx android.PackageVarContext) string { + return getMacTools(ctx).lipoPath + }) + pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string { return getMacTools(ctx).stripPath }) @@ -118,6 +123,7 @@ type macPlatformTools struct { sdkRoot string arPath string + lipoPath string stripPath string toolPath string } @@ -157,6 +163,7 @@ func getMacTools(ctx android.PathContext) *macPlatformTools { macTools.sdkRoot = xcrun("--show-sdk-path") macTools.arPath = xcrun("--find", "ar") + macTools.lipoPath = xcrun("--find", "lipo") macTools.stripPath = xcrun("--find", "strip") macTools.toolPath = filepath.Dir(xcrun("--find", "ld")) }) diff --git a/cc/config/global.go b/cc/config/global.go index 0b229be76..a340e465e 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -46,7 +46,6 @@ var ( "-O2", "-g", - "-fdebug-info-for-profiling", "-fno-strict-aliasing", @@ -125,6 +124,9 @@ var ( "-Werror=sequence-point", "-Werror=format-security", "-nostdlibinc", + + // Emit additional debug info for AutoFDO + "-fdebug-info-for-profiling", } deviceGlobalCppflags = []string{ diff --git a/cc/fuzz.go b/cc/fuzz.go index e987fe43b..23d81d600 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -52,6 +52,10 @@ type fuzzBinary struct { installedSharedDeps []string } +func (fuzz *fuzzBinary) fuzzBinary() bool { + return true +} + func (fuzz *fuzzBinary) linkerProps() []interface{} { props := fuzz.binaryDecorator.linkerProps() props = append(props, &fuzz.fuzzPackagedModule.FuzzProperties) @@ -234,7 +238,7 @@ func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) { } func NewFuzz(hod android.HostOrDeviceSupported) *Module { - module, binary := NewBinary(hod) + module, binary := newBinary(hod, false) binary.baseInstaller = NewFuzzInstaller() module.sanitize.SetSanitizer(Fuzzer, true) diff --git a/cc/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp index 4debb1c45..b105a3029 100644 --- a/cc/libbuildversion/Android.bp +++ b/cc/libbuildversion/Android.bp @@ -14,8 +14,10 @@ cc_library_static { enabled: true, }, }, + min_sdk_version: "26", apex_available: [ "//apex_available:platform", "//apex_available:anyapex", ], + vendor_available: true, } diff --git a/cc/libbuildversion/libbuildversion.cpp b/cc/libbuildversion/libbuildversion.cpp index 5242025eb..1e01c1145 100644 --- a/cc/libbuildversion/libbuildversion.cpp +++ b/cc/libbuildversion/libbuildversion.cpp @@ -36,7 +36,11 @@ std::string GetBuildNumber() { return soong_build_number; } +#ifdef __ANDROID_VENDOR__ + const prop_info* pi = __system_property_find("ro.vendor.build.version.incremental"); +#else const prop_info* pi = __system_property_find("ro.build.version.incremental"); +#endif if (pi == nullptr) return ""; std::string property_value; diff --git a/cc/library.go b/cc/library.go index dbf927d61..216c12409 100644 --- a/cc/library.go +++ b/cc/library.go @@ -207,10 +207,6 @@ type FlagExporterProperties struct { func init() { RegisterLibraryBuildComponents(android.InitRegistrationContext) - - android.RegisterBp2BuildMutator("cc_library_static", CcLibraryStaticBp2Build) - android.RegisterBp2BuildMutator("cc_library_shared", CcLibrarySharedBp2Build) - android.RegisterBp2BuildMutator("cc_library", CcLibraryBp2Build) } func RegisterLibraryBuildComponents(ctx android.RegistrationContext) { @@ -236,12 +232,13 @@ type bazelCcLibraryAttributes struct { Hdrs bazel.LabelListAttribute - Deps bazel.LabelListAttribute - Implementation_deps bazel.LabelListAttribute - Dynamic_deps bazel.LabelListAttribute - Implementation_dynamic_deps bazel.LabelListAttribute - Whole_archive_deps bazel.LabelListAttribute - System_dynamic_deps bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Implementation_deps bazel.LabelListAttribute + Dynamic_deps bazel.LabelListAttribute + Implementation_dynamic_deps bazel.LabelListAttribute + Whole_archive_deps bazel.LabelListAttribute + Implementation_whole_archive_deps bazel.LabelListAttribute + System_dynamic_deps bazel.LabelListAttribute Export_includes bazel.StringListAttribute Export_system_includes bazel.StringListAttribute @@ -253,6 +250,7 @@ type bazelCcLibraryAttributes struct { Stl *string Cpp_std *string + C_std *string // This is shared only. Link_crt bazel.BoolAttribute @@ -275,21 +273,12 @@ type stripAttributes struct { None bazel.BoolAttribute } -func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { - m, ok := ctx.Module().(*Module) - if !ok || !m.ConvertWithBp2build(ctx) { - return - } - - if ctx.ModuleType() != "cc_library" { - return - } - +func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { // For some cc_library modules, their static variants are ready to be // converted, but not their shared variants. For these modules, delegate to // the cc_library_static bp2build converter temporarily instead. if android.GenerateCcLibraryStaticOnly(ctx.Module().Name()) { - ccSharedOrStaticBp2BuildMutatorInternal(ctx, m, "cc_library_static") + sharedOrStaticLibraryBp2Build(ctx, m, true) return } @@ -298,43 +287,89 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { baseAttributes := bp2BuildParseBaseProps(ctx, m) compilerAttrs := baseAttributes.compilerAttributes linkerAttrs := baseAttributes.linkerAttributes - exportedIncludes := bp2BuildParseExportedIncludes(ctx, m) + exportedIncludes := bp2BuildParseExportedIncludes(ctx, m, compilerAttrs.includes) srcs := compilerAttrs.srcs + sharedAttrs.Dynamic_deps.Add(baseAttributes.protoDependency) + staticAttrs.Deps.Add(baseAttributes.protoDependency) + asFlags := compilerAttrs.asFlags if compilerAttrs.asSrcs.IsEmpty() && sharedAttrs.Srcs_as.IsEmpty() && staticAttrs.Srcs_as.IsEmpty() { // Skip asflags for BUILD file simplicity if there are no assembly sources. asFlags = bazel.MakeStringListAttribute(nil) } - attrs := &bazelCcLibraryAttributes{ - Srcs: srcs, - Srcs_c: compilerAttrs.cSrcs, - Srcs_as: compilerAttrs.asSrcs, - Hdrs: compilerAttrs.hdrs, + staticCommonAttrs := staticOrSharedAttributes{ + Srcs: *srcs.Clone().Append(staticAttrs.Srcs), + Srcs_c: *compilerAttrs.cSrcs.Clone().Append(staticAttrs.Srcs_c), + Srcs_as: *compilerAttrs.asSrcs.Clone().Append(staticAttrs.Srcs_as), + Copts: *compilerAttrs.copts.Clone().Append(staticAttrs.Copts), + Hdrs: *compilerAttrs.hdrs.Clone().Append(staticAttrs.Hdrs), + + Deps: *linkerAttrs.deps.Clone().Append(staticAttrs.Deps), + Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(staticAttrs.Implementation_deps), + Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(staticAttrs.Dynamic_deps), + Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(staticAttrs.Implementation_dynamic_deps), + Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, + Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps), + System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps), + } + + sharedCommonAttrs := staticOrSharedAttributes{ + Srcs: *srcs.Clone().Append(sharedAttrs.Srcs), + Srcs_c: *compilerAttrs.cSrcs.Clone().Append(sharedAttrs.Srcs_c), + Srcs_as: *compilerAttrs.asSrcs.Clone().Append(sharedAttrs.Srcs_as), + Copts: *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts), + Hdrs: *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs), + + Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps), + Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps), + Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps), + Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps), + Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps), + System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps), + } + + staticTargetAttrs := &bazelCcLibraryStaticAttributes{ + staticOrSharedAttributes: staticCommonAttrs, - Copts: compilerAttrs.copts, Cppflags: compilerAttrs.cppFlags, Conlyflags: compilerAttrs.conlyFlags, Asflags: asFlags, - Implementation_deps: linkerAttrs.implementationDeps, - Deps: linkerAttrs.deps, - Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, - Dynamic_deps: linkerAttrs.dynamicDeps, - Whole_archive_deps: linkerAttrs.wholeArchiveDeps, - System_dynamic_deps: linkerAttrs.systemDynamicDeps, - Export_includes: exportedIncludes.Includes, - Export_system_includes: exportedIncludes.SystemIncludes, - Local_includes: compilerAttrs.localIncludes, - Absolute_includes: compilerAttrs.absoluteIncludes, - Linkopts: linkerAttrs.linkopts, - Link_crt: linkerAttrs.linkCrt, - Use_libcrt: linkerAttrs.useLibcrt, - Rtti: compilerAttrs.rtti, - Stl: compilerAttrs.stl, - Cpp_std: compilerAttrs.cppStd, + Export_includes: exportedIncludes.Includes, + Export_absolute_includes: exportedIncludes.AbsoluteIncludes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Use_libcrt: linkerAttrs.useLibcrt, + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, + + Features: linkerAttrs.features, + } + + sharedTargetAttrs := &bazelCcLibrarySharedAttributes{ + staticOrSharedAttributes: sharedCommonAttrs, + Cppflags: compilerAttrs.cppFlags, + Conlyflags: compilerAttrs.conlyFlags, + Asflags: asFlags, + + Export_includes: exportedIncludes.Includes, + Export_absolute_includes: exportedIncludes.AbsoluteIncludes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Linkopts: linkerAttrs.linkopts, + Link_crt: linkerAttrs.linkCrt, + Use_libcrt: linkerAttrs.useLibcrt, + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, Additional_linker_inputs: linkerAttrs.additionalLinkerInputs, @@ -345,20 +380,20 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { All: linkerAttrs.stripAll, None: linkerAttrs.stripNone, }, - - Shared: sharedAttrs, - - Static: staticAttrs, - Features: linkerAttrs.features, } - props := bazel.BazelTargetModuleProperties{ - Rule_class: "cc_library", - Bzl_load_location: "//build/bazel/rules:full_cc_library.bzl", + staticProps := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_library_static", + Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl", + } + sharedProps := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_library_shared", + Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl", } - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) + ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs) + ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs) } // cc_library creates both static and/or shared libraries for a device and/or @@ -373,6 +408,7 @@ func LibraryFactory() android.Module { staticLibrarySdkMemberType, staticAndSharedLibrarySdkMemberType, } + module.bazelable = true module.bazelHandler = &ccLibraryBazelHandler{module: module} return module.Init() } @@ -382,6 +418,7 @@ func LibraryStaticFactory() android.Module { module, library := NewLibrary(android.HostAndDeviceSupported) library.BuildOnlyStatic() module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType} + module.bazelable = true module.bazelHandler = &ccLibraryBazelHandler{module: module} return module.Init() } @@ -391,6 +428,7 @@ func LibrarySharedFactory() android.Module { module, library := NewLibrary(android.HostAndDeviceSupported) library.BuildOnlyShared() module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType} + module.bazelable = true module.bazelHandler = &ccLibraryBazelHandler{module: module} return module.Init() } @@ -409,6 +447,8 @@ func LibraryHostSharedFactory() android.Module { module, library := NewLibrary(android.HostSupported) library.BuildOnlyShared() module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType} + module.bazelable = true + module.bazelHandler = &ccLibraryBazelHandler{module: module} return module.Init() } @@ -1320,11 +1360,21 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, return outputFile } +func ndkSharedLibDeps(ctx ModuleContext) android.Paths { + if ctx.Module().(*Module).IsSdkVariant() { + // The NDK sysroot timestamp file depends on all the NDK + // sysroot header and shared library files. + return android.Paths{getNdkBaseTimestampFile(ctx)} + } + return nil +} + func (library *libraryDecorator) linkShared(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { var linkerDeps android.Paths linkerDeps = append(linkerDeps, flags.LdFlagsDeps...) + linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...) unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list") forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list") @@ -1373,6 +1423,12 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, builderFlags := flagsToBuilderFlags(flags) + if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() { + fatOutputFile := outputFile + outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName) + transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path()) + } + // Optimize out relinking against shared libraries whose interface hasn't changed by // depending on a table of contents file instead of the library itself. tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc") @@ -2349,30 +2405,12 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu return outputFile } -func ccSharedOrStaticBp2BuildMutator(ctx android.TopDownMutatorContext, modType string) { - module, ok := ctx.Module().(*Module) - if !ok { - // Not a cc module - return - } - if !module.ConvertWithBp2build(ctx) { - return - } - - ccSharedOrStaticBp2BuildMutatorInternal(ctx, module, modType) -} - -func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, module *Module, modType string) { - if modType != "cc_library_static" && modType != "cc_library_shared" { - panic("ccSharedOrStaticBp2BuildMutatorInternal only supports cc_library_{static,shared}") - } - isStatic := modType == "cc_library_static" - +func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) { baseAttributes := bp2BuildParseBaseProps(ctx, module) compilerAttrs := baseAttributes.compilerAttributes linkerAttrs := baseAttributes.linkerAttributes - exportedIncludes := bp2BuildParseExportedIncludes(ctx, module) + exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, compilerAttrs.includes) // Append shared/static{} stanza properties. These won't be specified on // cc_library_* itself, but may be specified in cc_defaults that this module @@ -2403,27 +2441,34 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, Copts: compilerAttrs.copts, Hdrs: compilerAttrs.hdrs, - Deps: linkerAttrs.deps, - Implementation_deps: linkerAttrs.implementationDeps, - Dynamic_deps: linkerAttrs.dynamicDeps, - Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, - Whole_archive_deps: linkerAttrs.wholeArchiveDeps, - System_dynamic_deps: linkerAttrs.systemDynamicDeps, + Deps: linkerAttrs.deps, + Implementation_deps: linkerAttrs.implementationDeps, + Dynamic_deps: linkerAttrs.dynamicDeps, + Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps, + Whole_archive_deps: linkerAttrs.wholeArchiveDeps, + Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, + System_dynamic_deps: linkerAttrs.systemDynamicDeps, } var attrs interface{} if isStatic { + commonAttrs.Deps.Add(baseAttributes.protoDependency) attrs = &bazelCcLibraryStaticAttributes{ staticOrSharedAttributes: commonAttrs, - Use_libcrt: linkerAttrs.useLibcrt, - Rtti: compilerAttrs.rtti, - Stl: compilerAttrs.stl, - Cpp_std: compilerAttrs.cppStd, - Export_includes: exportedIncludes.Includes, - Export_system_includes: exportedIncludes.SystemIncludes, - Local_includes: compilerAttrs.localIncludes, - Absolute_includes: compilerAttrs.absoluteIncludes, + Use_libcrt: linkerAttrs.useLibcrt, + Use_version_lib: linkerAttrs.useVersionLib, + + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, + + Export_includes: exportedIncludes.Includes, + Export_absolute_includes: exportedIncludes.AbsoluteIncludes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, Cppflags: compilerAttrs.cppFlags, Conlyflags: compilerAttrs.conlyFlags, @@ -2432,21 +2477,27 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, Features: linkerAttrs.features, } } else { + commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency) + attrs = &bazelCcLibrarySharedAttributes{ staticOrSharedAttributes: commonAttrs, Cppflags: compilerAttrs.cppFlags, Conlyflags: compilerAttrs.conlyFlags, Asflags: asFlags, - Linkopts: linkerAttrs.linkopts, - Link_crt: linkerAttrs.linkCrt, - Use_libcrt: linkerAttrs.useLibcrt, - Rtti: compilerAttrs.rtti, - Stl: compilerAttrs.stl, - Cpp_std: compilerAttrs.cppStd, + Linkopts: linkerAttrs.linkopts, + Link_crt: linkerAttrs.linkCrt, + Use_libcrt: linkerAttrs.useLibcrt, + Use_version_lib: linkerAttrs.useVersionLib, + + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + C_std: compilerAttrs.cStd, Export_includes: exportedIncludes.Includes, + Export_absolute_includes: exportedIncludes.AbsoluteIncludes, Export_system_includes: exportedIncludes.SystemIncludes, Local_includes: compilerAttrs.localIncludes, Absolute_includes: compilerAttrs.absoluteIncludes, @@ -2464,6 +2515,12 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, } } + var modType string + if isStatic { + modType = "cc_library_static" + } else { + modType = "cc_library_shared" + } props := bazel.BazelTargetModuleProperties{ Rule_class: modType, Bzl_load_location: fmt.Sprintf("//build/bazel/rules:%s.bzl", modType), @@ -2476,16 +2533,20 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, type bazelCcLibraryStaticAttributes struct { staticOrSharedAttributes - Use_libcrt bazel.BoolAttribute - Rtti bazel.BoolAttribute - Stl *string - Cpp_std *string + Use_libcrt bazel.BoolAttribute + Use_version_lib bazel.BoolAttribute - Export_includes bazel.StringListAttribute - Export_system_includes bazel.StringListAttribute - Local_includes bazel.StringListAttribute - Absolute_includes bazel.StringListAttribute - Hdrs bazel.LabelListAttribute + Rtti bazel.BoolAttribute + Stl *string + Cpp_std *string + C_std *string + + Export_includes bazel.StringListAttribute + Export_absolute_includes bazel.StringListAttribute + Export_system_includes bazel.StringListAttribute + Local_includes bazel.StringListAttribute + Absolute_includes bazel.StringListAttribute + Hdrs bazel.LabelListAttribute Cppflags bazel.StringListAttribute Conlyflags bazel.StringListAttribute @@ -2494,34 +2555,27 @@ type bazelCcLibraryStaticAttributes struct { Features bazel.StringListAttribute } -func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) { - isLibraryStatic := ctx.ModuleType() == "cc_library_static" - if b, ok := ctx.Module().(android.Bazelable); ok { - // This is created by a custom soong config module type, so its ctx.ModuleType() is not - // cc_library_static. Check its BaseModuleType. - isLibraryStatic = isLibraryStatic || b.BaseModuleType() == "cc_library_static" - } - if isLibraryStatic { - ccSharedOrStaticBp2BuildMutator(ctx, "cc_library_static") - } -} - // TODO(b/199902614): Can this be factored to share with the other Attributes? type bazelCcLibrarySharedAttributes struct { staticOrSharedAttributes - Linkopts bazel.StringListAttribute - Link_crt bazel.BoolAttribute // Only for linking shared library (and cc_binary) - Use_libcrt bazel.BoolAttribute - Rtti bazel.BoolAttribute - Stl *string - Cpp_std *string + Linkopts bazel.StringListAttribute + Link_crt bazel.BoolAttribute // Only for linking shared library (and cc_binary) - Export_includes bazel.StringListAttribute - Export_system_includes bazel.StringListAttribute - Local_includes bazel.StringListAttribute - Absolute_includes bazel.StringListAttribute - Hdrs bazel.LabelListAttribute + Use_libcrt bazel.BoolAttribute + Use_version_lib bazel.BoolAttribute + + Rtti bazel.BoolAttribute + Stl *string + Cpp_std *string + C_std *string + + Export_includes bazel.StringListAttribute + Export_absolute_includes bazel.StringListAttribute + Export_system_includes bazel.StringListAttribute + Local_includes bazel.StringListAttribute + Absolute_includes bazel.StringListAttribute + Hdrs bazel.LabelListAttribute Strip stripAttributes Additional_linker_inputs bazel.LabelListAttribute @@ -2532,15 +2586,3 @@ type bazelCcLibrarySharedAttributes struct { Features bazel.StringListAttribute } - -func CcLibrarySharedBp2Build(ctx android.TopDownMutatorContext) { - isLibraryShared := ctx.ModuleType() == "cc_library_shared" - if b, ok := ctx.Module().(android.Bazelable); ok { - // This is created by a custom soong config module type, so its ctx.ModuleType() is not - // cc_library_shared. Check its BaseModuleType. - isLibraryShared = isLibraryShared || b.BaseModuleType() == "cc_library_shared" - } - if isLibraryShared { - ccSharedOrStaticBp2BuildMutator(ctx, "cc_library_shared") - } -} diff --git a/cc/library_headers.go b/cc/library_headers.go index ede6ab3c0..70e4715ad 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -25,7 +25,6 @@ func init() { // Register sdk member types. android.RegisterSdkMemberType(headersLibrarySdkMemberType) - android.RegisterBp2BuildMutator("cc_library_headers", CcLibraryHeadersBp2Build) } var headersLibrarySdkMemberType = &librarySdkMemberType{ @@ -96,52 +95,41 @@ func LibraryHeaderFactory() android.Module { module, library := NewLibrary(android.HostAndDeviceSupported) library.HeaderOnly() module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType} + module.bazelable = true module.bazelHandler = &libraryHeaderBazelHander{module: module, library: library} return module.Init() } // cc_prebuilt_library_headers is a prebuilt version of cc_library_headers func prebuiltLibraryHeaderFactory() android.Module { - module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported) + module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "") library.HeaderOnly() return module.Init() } type bazelCcLibraryHeadersAttributes struct { - Hdrs bazel.LabelListAttribute - Export_includes bazel.StringListAttribute - Export_system_includes bazel.StringListAttribute - Deps bazel.LabelListAttribute - Implementation_deps bazel.LabelListAttribute - System_dynamic_deps bazel.LabelListAttribute + Hdrs bazel.LabelListAttribute + Export_includes bazel.StringListAttribute + Export_absolute_includes bazel.StringListAttribute + Export_system_includes bazel.StringListAttribute + Deps bazel.LabelListAttribute + Implementation_deps bazel.LabelListAttribute + System_dynamic_deps bazel.LabelListAttribute } -func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) { - module, ok := ctx.Module().(*Module) - if !ok { - // Not a cc module - return - } - - if !module.ConvertWithBp2build(ctx) { - return - } - - if ctx.ModuleType() != "cc_library_headers" { - return - } - - exportedIncludes := bp2BuildParseExportedIncludes(ctx, module) +func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { baseAttributes := bp2BuildParseBaseProps(ctx, module) + exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, baseAttributes.includes) linkerAttrs := baseAttributes.linkerAttributes attrs := &bazelCcLibraryHeadersAttributes{ - Export_includes: exportedIncludes.Includes, - Export_system_includes: exportedIncludes.SystemIncludes, - Implementation_deps: linkerAttrs.implementationDeps, - Deps: linkerAttrs.deps, - System_dynamic_deps: linkerAttrs.systemDynamicDeps, - Hdrs: baseAttributes.hdrs, + Export_includes: exportedIncludes.Includes, + Export_absolute_includes: exportedIncludes.AbsoluteIncludes, + Export_system_includes: exportedIncludes.SystemIncludes, + Implementation_deps: linkerAttrs.implementationDeps, + Deps: linkerAttrs.deps, + System_dynamic_deps: linkerAttrs.systemDynamicDeps, + Hdrs: baseAttributes.hdrs, } props := bazel.BazelTargetModuleProperties{ diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go index 564ef61fb..3e448ba26 100644 --- a/cc/library_headers_test.go +++ b/cc/library_headers_test.go @@ -15,48 +15,85 @@ package cc import ( - "strings" + "fmt" "testing" + + "android/soong/android" + + "github.com/google/blueprint" ) func TestLibraryHeaders(t *testing.T) { - ctx := testCc(t, ` - cc_library_headers { - name: "headers", - export_include_dirs: ["my_include"], - } - cc_library_static { - name: "lib", - srcs: ["foo.c"], - header_libs: ["headers"], - } - `) + bp := ` + %s { + name: "headers", + export_include_dirs: ["my_include"], + } + cc_library_static { + name: "lib", + srcs: ["foo.c"], + header_libs: ["headers"], + } + ` + + for _, headerModule := range []string{"cc_library_headers", "cc_prebuilt_library_headers"} { + t.Run(headerModule, func(t *testing.T) { + ctx := testCc(t, fmt.Sprintf(bp, headerModule)) - // test if header search paths are correctly added - cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc") - cflags := cc.Args["cFlags"] - if !strings.Contains(cflags, " -Imy_include ") { - t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags) + // test if header search paths are correctly added + cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc") + android.AssertStringDoesContain(t, "cFlags for lib module", cc.Args["cFlags"], " -Imy_include ") + + // Test that there's a valid AndroidMk entry. + headers := ctx.ModuleForTests("headers", "android_arm64_armv8-a").Module() + e := android.AndroidMkEntriesForTest(t, ctx, headers)[0] + + // This duplicates the tests done in AndroidMkEntries.write. It would be + // better to test its output, but there are no test functions that capture that. + android.AssertBoolEquals(t, "AndroidMkEntries.Disabled", false, e.Disabled) + android.AssertBoolEquals(t, "AndroidMkEntries.OutputFile.Valid()", true, e.OutputFile.Valid()) + + android.AssertStringListContains(t, "LOCAL_EXPORT_CFLAGS for headers module", e.EntryMap["LOCAL_EXPORT_CFLAGS"], "-Imy_include") + }) } } -func TestPrebuiltLibraryHeaders(t *testing.T) { - ctx := testCc(t, ` - cc_prebuilt_library_headers { - name: "headers", - export_include_dirs: ["my_include"], - } - cc_library_static { - name: "lib", - srcs: ["foo.c"], - header_libs: ["headers"], - } - `) +func TestPrebuiltLibraryHeadersPreferred(t *testing.T) { + bp := ` + cc_library_headers { + name: "headers", + export_include_dirs: ["my_include"], + } + cc_prebuilt_library_headers { + name: "headers", + prefer: %t, + export_include_dirs: ["my_include"], + } + cc_library_static { + name: "lib", + srcs: ["foo.c"], + header_libs: ["headers"], + } + ` - // test if header search paths are correctly added - cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc") - cflags := cc.Args["cFlags"] - if !strings.Contains(cflags, " -Imy_include ") { - t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags) + for _, prebuiltPreferred := range []bool{false, true} { + t.Run(fmt.Sprintf("prebuilt prefer %t", prebuiltPreferred), func(t *testing.T) { + ctx := testCc(t, fmt.Sprintf(bp, prebuiltPreferred)) + lib := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static") + sourceDep := ctx.ModuleForTests("headers", "android_arm64_armv8-a") + prebuiltDep := ctx.ModuleForTests("prebuilt_headers", "android_arm64_armv8-a") + hasSourceDep := false + hasPrebuiltDep := false + ctx.VisitDirectDeps(lib.Module(), func(dep blueprint.Module) { + if dep == sourceDep.Module() { + hasSourceDep = true + } + if dep == prebuiltDep.Module() { + hasPrebuiltDep = true + } + }) + android.AssertBoolEquals(t, "depends on source headers", !prebuiltPreferred, hasSourceDep) + android.AssertBoolEquals(t, "depends on prebuilt headers", prebuiltPreferred, hasPrebuiltDep) + }) } } diff --git a/cc/library_test.go b/cc/library_test.go index 7ddfaa7fd..d220e19f8 100644 --- a/cc/library_test.go +++ b/cc/library_test.go @@ -257,9 +257,16 @@ cc_library { CcObjectFiles: []string{"foo.o"}, Includes: []string{"include"}, SystemIncludes: []string{"system_include"}, - RootStaticArchives: []string{"foo.a"}, + Headers: []string{"foo.h"}, RootDynamicLibraries: []string{"foo.so"}, }, + "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{ + CcObjectFiles: []string{"foo.o"}, + Includes: []string{"include"}, + SystemIncludes: []string{"system_include"}, + Headers: []string{"foo.h"}, + RootStaticArchives: []string{"foo.a"}, + }, }, } ctx := testCcWithConfig(t, config) @@ -273,18 +280,25 @@ cc_library { expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) + flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo) + android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) + android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) + sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("") if err != nil { - t.Errorf("Unexpected error getting cc_object outputfiles %s", err) + t.Errorf("Unexpected error getting cc_library outputfiles %s", err) } expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"} android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) - entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0] - expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"} - gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"] - android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags) + flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo) + android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) + android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) + android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) } func TestLibraryVersionScript(t *testing.T) { diff --git a/cc/linkable.go b/cc/linkable.go index 560c9debe..02d7047bf 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -384,9 +384,13 @@ func flagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) includes := android.PathsForBazelOut(ctx, ccInfo.Includes) systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes) + headers := android.PathsForBazelOut(ctx, ccInfo.Headers) return FlagExporterInfo{ IncludeDirs: android.FirstUniquePaths(includes), SystemIncludeDirs: android.FirstUniquePaths(systemIncludes), + GeneratedHeaders: headers, + // necessary to ensure generated headers are considered implicit deps of dependent actions + Deps: headers, } } diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index fd458d96b..6c200f5dd 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -82,6 +82,12 @@ func getNdkBaseTimestampFile(ctx android.PathContext) android.WritablePath { return android.PathForOutput(ctx, "ndk_base.timestamp") } +// The headers timestamp file depends only on the NDK headers. +// This is used mainly for .tidy files that do not need any stub libraries. +func getNdkHeadersTimestampFile(ctx android.PathContext) android.WritablePath { + return android.PathForOutput(ctx, "ndk_headers.timestamp") +} + // The full timestamp file depends on the base timestamp *and* the static // libraries. func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath { @@ -96,6 +102,7 @@ type ndkSingleton struct{} func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { var staticLibInstallPaths android.Paths + var headerPaths android.Paths var installPaths android.Paths var licensePaths android.Paths ctx.VisitAllModules(func(module android.Module) { @@ -104,16 +111,19 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { } if m, ok := module.(*headerModule); ok { + headerPaths = append(headerPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } if m, ok := module.(*versionedHeaderModule); ok { + headerPaths = append(headerPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } if m, ok := module.(*preprocessedHeadersModule); ok { + headerPaths = append(headerPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } @@ -153,6 +163,12 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { Validation: getNdkAbiDiffTimestampFile(ctx), }) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Touch, + Output: getNdkHeadersTimestampFile(ctx), + Implicits: headerPaths, + }) + fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx)) // There's a phony "ndk" rule defined in core/main.mk that depends on this. diff --git a/cc/object.go b/cc/object.go index 0327a451a..bd43e3670 100644 --- a/cc/object.go +++ b/cc/object.go @@ -29,7 +29,6 @@ func init() { android.RegisterModuleType("cc_object", ObjectFactory) android.RegisterSdkMemberType(ccObjectSdkMemberType) - android.RegisterBp2BuildMutator("cc_object", ObjectBp2Build) } var ccObjectSdkMemberType = &librarySdkMemberType{ @@ -117,6 +116,7 @@ func ObjectFactory() android.Module { module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType} + module.bazelable = true return module.Init() } @@ -135,19 +135,9 @@ type bazelObjectAttributes struct { Linker_script bazel.LabelAttribute } -// ObjectBp2Build is the bp2build converter from cc_object modules to the +// objectBp2Build is the bp2build converter from cc_object modules to the // Bazel equivalent target, plus any necessary include deps for the cc_object. -func ObjectBp2Build(ctx android.TopDownMutatorContext) { - m, ok := ctx.Module().(*Module) - if !ok || !m.ConvertWithBp2build(ctx) { - return - } - - // a Module can be something other than a cc_object. - if ctx.ModuleType() != "cc_object" { - return - } - +func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) { if m.compiler == nil { // a cc_object must have access to the compiler decorator for its props. ctx.ModuleErrorf("compiler must not be nil for a cc_object module") @@ -96,10 +96,6 @@ func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleConte flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag) return flags } -func (props *PgoProperties) addSamplingProfileGatherFlags(ctx ModuleContext, flags Flags) Flags { - flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...) - return flags -} func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath { profileFile := *props.Pgo.Profile_file @@ -313,10 +309,6 @@ func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags { if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink { // Instrumentation PGO use and gather flags cannot coexist. return props.addInstrumentationProfileGatherFlags(ctx, flags) - } else if props.ShouldProfileModule && props.isSampling() { - flags = props.addSamplingProfileGatherFlags(ctx, flags) - } else if ctx.DeviceConfig().SamplingPGO() { - flags = props.addSamplingProfileGatherFlags(ctx, flags) } if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") { diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 16945ac69..feae81266 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -32,8 +32,6 @@ func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory) ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory) ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory) - - android.RegisterBp2BuildMutator("cc_prebuilt_library_shared", PrebuiltLibrarySharedBp2Build) } type prebuiltLinkerInterface interface { @@ -197,7 +195,13 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, if p.header() { ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{}) - return nil + // Need to return an output path so that the AndroidMk logic doesn't skip + // the prebuilt header. For compatibility, in case Android.mk files use a + // header lib in LOCAL_STATIC_LIBRARIES, create an empty ar file as + // placeholder, just like non-prebuilt header modules do in linkStatic(). + ph := android.PathForModuleOut(ctx, ctx.ModuleName()+staticLibraryExtension) + transformObjToStaticLib(ctx, nil, nil, builderFlags{}, ph, nil, nil) + return ph } return nil @@ -235,7 +239,7 @@ func (p *prebuiltLibraryLinker) implementationModuleName(name string) string { return android.RemoveOptionalPrebuiltPrefix(name) } -func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { +func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string) (*Module, *libraryDecorator) { module, library := NewLibrary(hod) module.compiler = nil @@ -247,11 +251,15 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec module.AddProperties(&prebuilt.properties) - srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string { - return prebuilt.prebuiltSrcs(ctx) - } + if srcsProperty == "" { + android.InitPrebuiltModuleWithoutSrcs(module) + } else { + srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string { + return prebuilt.prebuiltSrcs(ctx) + } - android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") + android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcsProperty) + } // Prebuilt libraries can be used in SDKs. android.InitSdkAwareModule(module) @@ -261,7 +269,7 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec // cc_prebuilt_library installs a precompiled shared library that are // listed in the srcs property in the device's directory. func PrebuiltLibraryFactory() android.Module { - module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported) + module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported, "srcs") // Prebuilt shared libraries can be included in APEXes android.InitApexModule(module) @@ -280,15 +288,16 @@ func PrebuiltSharedLibraryFactory() android.Module { // to be used as a data dependency of a test-related module (such as cc_test, or // cc_test_library). func PrebuiltSharedTestLibraryFactory() android.Module { - module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported) + module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "srcs") library.BuildOnlyShared() library.baseInstaller = NewTestInstaller() return module.Init() } func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { - module, library := NewPrebuiltLibrary(hod) + module, library := NewPrebuiltLibrary(hod, "srcs") library.BuildOnlyShared() + module.bazelable = true // Prebuilt shared libraries can be included in APEXes android.InitApexModule(module) @@ -304,33 +313,43 @@ func PrebuiltStaticLibraryFactory() android.Module { } func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { - module, library := NewPrebuiltLibrary(hod) + module, library := NewPrebuiltLibrary(hod, "srcs") library.BuildOnlyStatic() + module.bazelable = true module.bazelHandler = &prebuiltStaticLibraryBazelHandler{module: module, library: library} return module, library } -type bazelPrebuiltLibrarySharedAttributes struct { - Shared_library bazel.LabelAttribute +type bazelPrebuiltLibraryStaticAttributes struct { + Static_library bazel.LabelAttribute + Export_includes bazel.StringListAttribute + Export_system_includes bazel.StringListAttribute } -func PrebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext) { - module, ok := ctx.Module().(*Module) - if !ok { - // Not a cc module - return - } - if !module.ConvertWithBp2build(ctx) { - return +func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module) { + prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module) + exportedIncludes := Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx, module) + + attrs := &bazelPrebuiltLibraryStaticAttributes{ + Static_library: prebuiltAttrs.Src, + Export_includes: exportedIncludes.Includes, + Export_system_includes: exportedIncludes.SystemIncludes, } - if ctx.ModuleType() != "cc_prebuilt_library_shared" { - return + + props := bazel.BazelTargetModuleProperties{ + Rule_class: "prebuilt_library_static", + Bzl_load_location: "//build/bazel/rules:prebuilt_library_static.bzl", } - prebuiltLibrarySharedBp2BuildInternal(ctx, module) + name := android.RemoveOptionalPrebuiltPrefix(module.Name()) + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) +} + +type bazelPrebuiltLibrarySharedAttributes struct { + Shared_library bazel.LabelAttribute } -func prebuiltLibrarySharedBp2BuildInternal(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) { prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module) attrs := &bazelPrebuiltLibrarySharedAttributes{ @@ -533,7 +552,7 @@ func prebuiltBinaryFactory() android.Module { } func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { - module, binary := NewBinary(hod) + module, binary := newBinary(hod, false) module.compiler = nil prebuilt := &prebuiltBinaryLinker{ diff --git a/cc/proto.go b/cc/proto.go index 44661447c..f3410bc2b 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -16,8 +16,14 @@ package cc import ( "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bazel" +) + +const ( + protoTypeDefault = "lite" ) // genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns @@ -63,7 +69,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo var lib string if String(p.Proto.Plugin) == "" { - switch String(p.Proto.Type) { + switch proptools.StringDefault(p.Proto.Type, protoTypeDefault) { case "full": if ctx.useSdk() { lib = "libprotobuf-cpp-full-ndk" @@ -71,7 +77,7 @@ func protoDeps(ctx DepsContext, deps Deps, p *android.ProtoProperties, static bo } else { lib = "libprotobuf-cpp-full" } - case "lite", "": + case "lite": if ctx.useSdk() { lib = "libprotobuf-cpp-lite-ndk" static = true @@ -157,3 +163,69 @@ func protoFlags(ctx ModuleContext, flags Flags, p *android.ProtoProperties) Flag return flags } + +type protoAttributes struct { + Deps bazel.LabelListAttribute +} + +type bp2buildProtoDeps struct { + wholeStaticLib *bazel.LabelAttribute + implementationWholeStaticLib *bazel.LabelAttribute + protoDep *bazel.LabelAttribute +} + +func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps { + var ret bp2buildProtoDeps + + protoInfo, ok := android.Bp2buildProtoProperties(ctx, m, protoSrcs) + if !ok { + return ret + } + + var depName string + typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault) + var rule_class string + suffix := "_cc_proto" + switch typ { + case "lite": + suffix += "_lite" + rule_class = "cc_lite_proto_library" + depName = "libprotobuf-cpp-lite" + case "full": + rule_class = "cc_proto_library" + depName = "libprotobuf-cpp-full" + default: + ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ) + } + + dep := android.BazelLabelForModuleDepSingle(ctx, depName) + ret.protoDep = &bazel.LabelAttribute{Value: &dep} + + protoLabel := bazel.Label{Label: ":" + protoInfo.Name} + var protoAttrs protoAttributes + protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}}) + + name := m.Name() + suffix + + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: rule_class, + Bzl_load_location: "//build/bazel/rules:cc_proto.bzl", + }, + android.CommonAttributes{Name: name}, + &protoAttrs) + + var privateHdrs bool + if lib, ok := m.linker.(*libraryDecorator); ok { + privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers) + } + + labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}} + if privateHdrs { + ret.implementationWholeStaticLib = labelAttr + } else { + ret.wholeStaticLib = labelAttr + } + + return ret +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 93d4b4c54..d7b1adee5 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -35,7 +35,6 @@ var ( asanCflags = []string{ "-fno-omit-frame-pointer", - "-fno-experimental-new-pass-manager", } asanLdflags = []string{"-Wl,-u,__asan_preinit"} @@ -666,9 +665,6 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth") flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth") - // TODO(b/133876586): Experimental PM breaks sanitizer coverage. - flags.Local.CFlags = append(flags.Local.CFlags, "-fno-experimental-new-pass-manager") - // Disable fortify for fuzzing builds. Generally, we'll be building with // UBSan or ASan here and the fortify checks pollute the stack traces. flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE") diff --git a/cc/test.go b/cc/test.go index f37fdae38..d8b7833ba 100644 --- a/cc/test.go +++ b/cc/test.go @@ -105,11 +105,6 @@ type TestBinaryProperties struct { // Add RunCommandTargetPreparer to stop framework before the test and start it after the test. Disable_framework *bool - // Add ShippingApiLevelModuleController to auto generated test config. If the device properties - // for the shipping api level is less than the test_min_api_level, skip this module. - // Deprecated (b/187258404). Use test_options.min_shipping_api_level instead. - Test_min_api_level *int64 - // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. @@ -432,14 +427,6 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { var options []tradefed.Option options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)}) configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) - } else if test.Properties.Test_min_api_level != nil { - // TODO: (b/187258404) Remove test.Properties.Test_min_api_level - if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { - ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") - } - var options []tradefed.Option - options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)}) - configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) } if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { var options []tradefed.Option @@ -474,7 +461,7 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { } func NewTest(hod android.HostOrDeviceSupported) *Module { - module, binary := NewBinary(hod) + module, binary := newBinary(hod, false) module.multilib = android.MultilibBoth binary.baseInstaller = NewTestInstaller() @@ -564,6 +551,10 @@ type benchmarkDecorator struct { testConfig android.Path } +func (benchmark *benchmarkDecorator) benchmarkBinary() bool { + return true +} + func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) { runpath := "../../lib" if ctx.toolchain().Is64Bit() { @@ -601,7 +592,7 @@ func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Pat } func NewBenchmark(hod android.HostOrDeviceSupported) *Module { - module, binary := NewBinary(hod) + module, binary := newBinary(hod, false) module.multilib = android.MultilibBoth binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData) diff --git a/cc/tidy.go b/cc/tidy.go index 53ff1564b..78a791faf 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -15,6 +15,7 @@ package cc import ( + "path/filepath" "regexp" "strings" @@ -183,3 +184,154 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags { } return flags } + +func init() { + android.RegisterSingletonType("tidy_phony_targets", TidyPhonySingleton) +} + +// This TidyPhonySingleton generates both tidy-* and obj-* phony targets for C/C++ files. +func TidyPhonySingleton() android.Singleton { + return &tidyPhonySingleton{} +} + +type tidyPhonySingleton struct{} + +// Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup. +func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module, + tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) { + allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths + allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths + subsetObjFileGroups := make(map[string]android.Paths) // subset group name => obj file Paths + subsetTidyFileGroups := make(map[string]android.Paths) // subset group name => tidy file Paths + + // (1) Collect all obj/tidy files into OS-specific groups. + ctx.VisitAllModuleVariants(module, func(variant android.Module) { + if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(variant) { + return + } + if m, ok := variant.(*Module); ok { + osName := variant.Target().Os.Name + addToOSGroup(osName, m.objFiles, allObjFileGroups, subsetObjFileGroups) + addToOSGroup(osName, m.tidyFiles, allTidyFileGroups, subsetTidyFileGroups) + } + }) + + // (2) Add an all-OS group, with "" or "subset" name, to include all os-specific phony targets. + addAllOSGroup(ctx, module, allObjFileGroups, "", "obj") + addAllOSGroup(ctx, module, allTidyFileGroups, "", "tidy") + addAllOSGroup(ctx, module, subsetObjFileGroups, "subset", "obj") + addAllOSGroup(ctx, module, subsetTidyFileGroups, "subset", "tidy") + + tidyTargetGroups := make(map[string]android.Path) + objTargetGroups := make(map[string]android.Path) + genObjTidyPhonyTargets(ctx, module, "obj", allObjFileGroups, objTargetGroups) + genObjTidyPhonyTargets(ctx, module, "obj", subsetObjFileGroups, objTargetGroups) + genObjTidyPhonyTargets(ctx, module, "tidy", allTidyFileGroups, tidyTargetGroups) + genObjTidyPhonyTargets(ctx, module, "tidy", subsetTidyFileGroups, tidyTargetGroups) + + moduleDir := ctx.ModuleDir(module) + appendToModulesInDirGroup(tidyTargetGroups, moduleDir, tidyModulesInDirGroup) + appendToModulesInDirGroup(objTargetGroups, moduleDir, objModulesInDirGroup) +} + +func (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) { + // For tidy-* directory phony targets, there are different variant groups. + // tidyModulesInDirGroup[G][D] is for group G, directory D, with Paths + // of all phony targets to be included into direct dependents of tidy-D_G. + tidyModulesInDirGroup := make(map[string]map[string]android.Paths) + // Also for obj-* directory phony targets. + objModulesInDirGroup := make(map[string]map[string]android.Paths) + + // Collect tidy/obj targets from the 'final' modules. + ctx.VisitAllModules(func(module android.Module) { + if module == ctx.FinalModule(module) { + collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup) + } + }) + + suffix := "" + if ctx.Config().KatiEnabled() { + suffix = "-soong" + } + generateObjTidyPhonyTargets(ctx, suffix, "obj", objModulesInDirGroup) + generateObjTidyPhonyTargets(ctx, suffix, "tidy", tidyModulesInDirGroup) +} + +// The name for an obj/tidy module variant group phony target is Name_group-obj/tidy, +func objTidyModuleGroupName(module android.Module, group string, suffix string) string { + if group == "" { + return module.Name() + "-" + suffix + } + return module.Name() + "_" + group + "-" + suffix +} + +// Generate obj-* or tidy-* phony targets. +func generateObjTidyPhonyTargets(ctx android.SingletonContext, suffix string, prefix string, objTidyModulesInDirGroup map[string]map[string]android.Paths) { + // For each variant group, create a <prefix>-<directory>_group target that + // depends on all subdirectories and modules in the directory. + for group, modulesInDir := range objTidyModulesInDirGroup { + groupSuffix := "" + if group != "" { + groupSuffix = "_" + group + } + mmTarget := func(dir string) string { + return prefix + "-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) + groupSuffix + } + dirs, topDirs := android.AddAncestors(ctx, modulesInDir, mmTarget) + // Create a <prefix>-soong_group target that depends on all <prefix>-dir_group of top level dirs. + var topDirPaths android.Paths + for _, dir := range topDirs { + topDirPaths = append(topDirPaths, android.PathForPhony(ctx, mmTarget(dir))) + } + ctx.Phony(prefix+suffix+groupSuffix, topDirPaths...) + // Create a <prefix>-dir_group target that depends on all targets in modulesInDir[dir] + for _, dir := range dirs { + if dir != "." && dir != "" { + ctx.Phony(mmTarget(dir), modulesInDir[dir]...) + } + } + } +} + +// Append (obj|tidy)TargetGroups[group] into (obj|tidy)ModulesInDirGroups[group][moduleDir]. +func appendToModulesInDirGroup(targetGroups map[string]android.Path, moduleDir string, modulesInDirGroup map[string]map[string]android.Paths) { + for group, phonyPath := range targetGroups { + if _, found := modulesInDirGroup[group]; !found { + modulesInDirGroup[group] = make(map[string]android.Paths) + } + modulesInDirGroup[group][moduleDir] = append(modulesInDirGroup[group][moduleDir], phonyPath) + } +} + +// Add given files to the OS group and subset group. +func addToOSGroup(osName string, files android.Paths, allGroups, subsetGroups map[string]android.Paths) { + if len(files) > 0 { + subsetName := osName + "_subset" + allGroups[osName] = append(allGroups[osName], files...) + // Now include only the first variant in the subsetGroups. + // If clang and clang-tidy get faster, we might include more variants. + if _, found := subsetGroups[subsetName]; !found { + subsetGroups[subsetName] = files + } + } +} + +// Add an all-OS group, with groupName, to include all os-specific phony targets. +func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) { + if len(phonyTargetGroups) > 0 { + var targets android.Paths + for group, _ := range phonyTargetGroups { + targets = append(targets, android.PathForPhony(ctx, objTidyModuleGroupName(module, group, objTidyName))) + } + phonyTargetGroups[groupName] = targets + } +} + +// Create one phony targets for each group and add them to the targetGroups. +func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) { + for group, files := range fileGroups { + groupName := objTidyModuleGroupName(module, group, objTidyName) + ctx.Phony(groupName, files...) + targetGroups[group] = android.PathForPhony(ctx, groupName) + } +} |