diff options
| -rw-r--r-- | android/arch.go | 320 | ||||
| -rw-r--r-- | android/bazel.go | 75 | ||||
| -rw-r--r-- | bp2build/conversion.go | 2 | ||||
| -rw-r--r-- | cc/bp2build.go | 8 | ||||
| -rw-r--r-- | cmd/soong_build/main.go | 87 | ||||
| -rw-r--r-- | rust/rust.go | 4 |
6 files changed, 298 insertions, 198 deletions
diff --git a/android/arch.go b/android/arch.go index bb1b61366..10c827ba2 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1055,24 +1055,28 @@ func mergePropertyStruct(ctx ArchVariantContext, dst interface{}, srcValue refle // Returns the immediate child of the input property struct that corresponds to // the sub-property "field". func getChildPropertyStruct(ctx ArchVariantContext, - src reflect.Value, field, userFriendlyField string) reflect.Value { + src reflect.Value, field, userFriendlyField string) (reflect.Value, bool) { // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { - return src + return reflect.Value{}, false } src = src.Elem() } // Find the requested field in the src struct. - src = src.FieldByName(proptools.FieldNameForProperty(field)) - if !src.IsValid() { + child := src.FieldByName(proptools.FieldNameForProperty(field)) + if !child.IsValid() { ctx.ModuleErrorf("field %q does not exist", userFriendlyField) - return src + return reflect.Value{}, false + } + + if child.IsZero() { + return reflect.Value{}, false } - return src + return child, true } // Squash the appropriate OS-specific property structs into the matching top level property structs @@ -1099,8 +1103,9 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { if os.Class == Host { field := "Host" prefix := "target.host" - hostProperties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, hostProperties) + if hostProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, hostProperties) + } } // Handle target OS generalities of the form: @@ -1112,15 +1117,17 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { if os.Linux() { field := "Linux" prefix := "target.linux" - linuxProperties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, linuxProperties) + if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, linuxProperties) + } } if os.Bionic() { field := "Bionic" prefix := "target.bionic" - bionicProperties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, bionicProperties) + if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, bionicProperties) + } } // Handle target OS properties in the form: @@ -1137,14 +1144,16 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { // }, field := os.Field prefix := "target." + os.Name - osProperties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, osProperties) + if osProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, osProperties) + } if os.Class == Host && os != Windows { field := "Not_windows" prefix := "target.not_windows" - notWindowsProperties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, notWindowsProperties) + if notWindowsProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, notWindowsProperties) + } } // Handle 64-bit device properties in the form: @@ -1164,13 +1173,15 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { if ctx.Config().Android64() { field := "Android64" prefix := "target.android64" - android64Properties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, android64Properties) + if android64Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, android64Properties) + } } else { field := "Android32" prefix := "target.android32" - android32Properties := getChildPropertyStruct(ctx, targetProp, field, prefix) - mergePropertyStruct(ctx, genProps, android32Properties) + if android32Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok { + mergePropertyStruct(ctx, genProps, android32Properties) + } } } } @@ -1186,12 +1197,11 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { // }, // This struct will also contain sub-structs containing to the architecture/CPU // variants and features that themselves contain properties specific to those. -func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value { +func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { archPropValues := reflect.ValueOf(archProperties).Elem() archProp := archPropValues.FieldByName("Arch").Elem() prefix := "arch." + archType.Name - archStruct := getChildPropertyStruct(ctx, archProp, archType.Name, prefix) - return archStruct + return getChildPropertyStruct(ctx, archProp, archType.Name, prefix) } // Returns the struct containing the properties specific to a given multilib @@ -1201,11 +1211,10 @@ func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archT // key: value, // }, // }, -func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) reflect.Value { +func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { archPropValues := reflect.ValueOf(archProperties).Elem() multilibProp := archPropValues.FieldByName("Multilib").Elem() - multilibProperties := getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib) - return multilibProperties + return getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib) } // Returns the structs corresponding to the properties specific to the given @@ -1219,57 +1228,63 @@ func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch archType := arch.ArchType if arch.ArchType != Common { - archStruct := getArchTypeStruct(ctx, archProperties, arch.ArchType) - result = append(result, archStruct) - - // Handle arch-variant-specific properties in the form: - // arch: { - // arm: { - // variant: { - // key: value, - // }, - // }, - // }, - v := variantReplacer.Replace(arch.ArchVariant) - if v != "" { - prefix := "arch." + archType.Name + "." + v - variantProperties := getChildPropertyStruct(ctx, archStruct, v, prefix) - result = append(result, variantProperties) - } - - // Handle cpu-variant-specific properties in the form: - // arch: { - // arm: { - // variant: { - // key: value, - // }, - // }, - // }, - if arch.CpuVariant != arch.ArchVariant { - c := variantReplacer.Replace(arch.CpuVariant) - if c != "" { - prefix := "arch." + archType.Name + "." + c - cpuVariantProperties := getChildPropertyStruct(ctx, archStruct, c, prefix) - result = append(result, cpuVariantProperties) + archStruct, ok := getArchTypeStruct(ctx, archProperties, arch.ArchType) + if ok { + result = append(result, archStruct) + + // Handle arch-variant-specific properties in the form: + // arch: { + // arm: { + // variant: { + // key: value, + // }, + // }, + // }, + v := variantReplacer.Replace(arch.ArchVariant) + if v != "" { + prefix := "arch." + archType.Name + "." + v + if variantProperties, ok := getChildPropertyStruct(ctx, archStruct, v, prefix); ok { + result = append(result, variantProperties) + } } - } - // Handle arch-feature-specific properties in the form: - // arch: { - // arm: { - // feature: { - // key: value, - // }, - // }, - // }, - for _, feature := range arch.ArchFeatures { - prefix := "arch." + archType.Name + "." + feature - featureProperties := getChildPropertyStruct(ctx, archStruct, feature, prefix) - result = append(result, featureProperties) + // Handle cpu-variant-specific properties in the form: + // arch: { + // arm: { + // variant: { + // key: value, + // }, + // }, + // }, + if arch.CpuVariant != arch.ArchVariant { + c := variantReplacer.Replace(arch.CpuVariant) + if c != "" { + prefix := "arch." + archType.Name + "." + c + if cpuVariantProperties, ok := getChildPropertyStruct(ctx, archStruct, c, prefix); ok { + result = append(result, cpuVariantProperties) + } + } + } + + // Handle arch-feature-specific properties in the form: + // arch: { + // arm: { + // feature: { + // key: value, + // }, + // }, + // }, + for _, feature := range arch.ArchFeatures { + prefix := "arch." + archType.Name + "." + feature + if featureProperties, ok := getChildPropertyStruct(ctx, archStruct, feature, prefix); ok { + result = append(result, featureProperties) + } + } } - multilibProperties := getMultilibStruct(ctx, archProperties, archType) - result = append(result, multilibProperties) + if multilibProperties, ok := getMultilibStruct(ctx, archProperties, archType); ok { + result = append(result, multilibProperties) + } // Handle combined OS-feature and arch specific properties in the form: // target: { @@ -1280,15 +1295,17 @@ func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch if os.Linux() { field := "Linux_" + arch.ArchType.Name userFriendlyField := "target.linux_" + arch.ArchType.Name - linuxProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField) - result = append(result, linuxProperties) + if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { + result = append(result, linuxProperties) + } } if os.Bionic() { field := "Bionic_" + archType.Name userFriendlyField := "target.bionic_" + archType.Name - bionicProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField) - result = append(result, bionicProperties) + if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { + result = append(result, bionicProperties) + } } // Handle combined OS and arch specific properties in the form: @@ -1308,8 +1325,9 @@ func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch // }, field := os.Field + "_" + archType.Name userFriendlyField := "target." + os.Name + "_" + archType.Name - osArchProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField) - result = append(result, osArchProperties) + if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { + result = append(result, osArchProperties) + } } // Handle arm on x86 properties in the form: @@ -1326,21 +1344,24 @@ func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch hasArmAndroidArch(ctx.Config().Targets[Android])) { field := "Arm_on_x86" userFriendlyField := "target.arm_on_x86" - armOnX86Properties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField) - result = append(result, armOnX86Properties) + if armOnX86Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { + result = append(result, armOnX86Properties) + } } if arch.ArchType == X86_64 && (hasArmAbi(arch) || hasArmAndroidArch(ctx.Config().Targets[Android])) { field := "Arm_on_x86_64" userFriendlyField := "target.arm_on_x86_64" - armOnX8664Properties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField) - result = append(result, armOnX8664Properties) + if armOnX8664Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok { + result = append(result, armOnX8664Properties) + } } if os == Android && nativeBridgeEnabled { userFriendlyField := "Native_bridge" prefix := "target.native_bridge" - nativeBridgeProperties := getChildPropertyStruct(ctx, targetProp, userFriendlyField, prefix) - result = append(result, nativeBridgeProperties) + if nativeBridgeProperties, ok := getChildPropertyStruct(ctx, targetProp, userFriendlyField, prefix); ok { + result = append(result, nativeBridgeProperties) + } } } @@ -1869,6 +1890,8 @@ type ArchVariantContext interface { // For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }` // will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given // propertyset contains `Foo []string`. +// +// Implemented in a way very similar to GetTargetProperties(). func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet interface{}) map[ArchType]interface{} { // Return value of the arch types to the prop values for that arch. archToProp := map[ArchType]interface{}{} @@ -1903,9 +1926,14 @@ func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet inter // input one that contains the data specific to that arch. propertyStructs := make([]reflect.Value, 0) for _, archProperty := range archProperties { - archTypeStruct := getArchTypeStruct(ctx, archProperty, arch) - multilibStruct := getMultilibStruct(ctx, archProperty, arch) - propertyStructs = append(propertyStructs, archTypeStruct, multilibStruct) + archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch) + if ok { + propertyStructs = append(propertyStructs, archTypeStruct) + } + multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch) + if ok { + propertyStructs = append(propertyStructs, multilibStruct) + } } // Create a new instance of the requested property set @@ -1922,18 +1950,31 @@ func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet inter return archToProp } +// Returns the struct containing the properties specific to the given +// architecture type. These look like this in Blueprint files: +// target: { +// android: { +// key: value, +// }, +// }, +// This struct will also contain sub-structs containing to the architecture/CPU +// variants and features that themselves contain properties specific to those. +func getTargetStruct(ctx ArchVariantContext, archProperties interface{}, os OsType) (reflect.Value, bool) { + archPropValues := reflect.ValueOf(archProperties).Elem() + targetProp := archPropValues.FieldByName("Target").Elem() + return getChildPropertyStruct(ctx, targetProp, os.Field, os.Field) +} + // GetTargetProperties returns a map of OS target (e.g. android, windows) to the -// values of the properties of the 'dst' struct that are specific to that OS -// target. +// values of the properties of the 'propertySet' struct that are specific to +// that OS target. // // For example, passing a struct { Foo bool, Bar string } will return an // interface{} that can be type asserted back into the same struct, containing // the os-specific property value specified by the module if defined. // -// While this looks similar to GetArchProperties, the internal representation of -// the properties have a slightly different layout to warrant a standalone -// lookup function. -func (m *ModuleBase) GetTargetProperties(dst interface{}) map[OsType]interface{} { +// Implemented in a way very similar to GetArchProperties(). +func (m *ModuleBase) GetTargetProperties(ctx ArchVariantContext, propertySet interface{}) map[OsType]interface{} { // Return value of the arch types to the prop values for that arch. osToProp := map[OsType]interface{}{} @@ -1942,69 +1983,48 @@ func (m *ModuleBase) GetTargetProperties(dst interface{}) map[OsType]interface{} return osToProp } - // archProperties has the type of [][]interface{}. Looks complicated, so - // let's explain this step by step. - // - // Loop over the outer index, which determines the property struct that - // contains a matching set of properties in dst that we're interested in. - // For example, BaseCompilerProperties or BaseLinkerProperties. - for i := range m.archProperties { - if m.archProperties[i] == nil { - continue - } - - // Iterate over the supported OS types - for _, os := range osTypeList { - // e.g android, linux_bionic - field := os.Field - - // If it's not nil, loop over the inner index, which determines the arch variant - // of the prop type. In an Android.bp file, this is like looping over: - // - // target: { android: { key: value, ... }, linux_bionic: { key: value, ... } } - for _, archProperties := range m.archProperties[i] { - archPropValues := reflect.ValueOf(archProperties).Elem() - - // This is the archPropRoot struct. Traverse into the Targetnested struct. - src := archPropValues.FieldByName("Target").Elem() - - // Step into non-nil pointers to structs in the src value. - if src.Kind() == reflect.Ptr { - if src.IsNil() { - continue - } - src = src.Elem() - } - - // Find the requested field (e.g. android, linux_bionic) in the src struct. - src = src.FieldByName(field) + dstType := reflect.ValueOf(propertySet).Type() + var archProperties []interface{} - // Validation steps. We want valid non-nil pointers to structs. - if !src.IsValid() || src.IsNil() { - continue - } + // First find the property set in the module that corresponds to the requested + // one. m.archProperties[i] corresponds to m.generalProperties[i]. + for i, generalProp := range m.generalProperties { + srcType := reflect.ValueOf(generalProp).Type() + if srcType == dstType { + archProperties = m.archProperties[i] + break + } + } - if src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct { - continue - } + if archProperties == nil { + // This module does not have the property set requested + return osToProp + } - // Clone the destination prop, since we want a unique prop struct per arch. - dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface() + for _, os := range osTypeList { + if os == CommonOS { + // It looks like this OS value is not used in Blueprint files + continue + } - // Copy the located property struct into the cloned destination property struct. - err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace) - if err != nil { - // This is fine, it just means the src struct doesn't match. - continue - } + propertyStructs := make([]reflect.Value, 0) + for _, archProperty := range archProperties { + targetStruct, ok := getTargetStruct(ctx, archProperty, os) + if ok { + propertyStructs = append(propertyStructs, targetStruct) + } + } - // Found the prop for the os, you have. - osToProp[os] = dstClone + // Create a new instance of the requested property set + value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() - // Go to the next prop. - break - } + // Merge all the structs together + for _, propertyStruct := range propertyStructs { + mergePropertyStruct(ctx, value, propertyStruct) } + + osToProp[os] = value } + return osToProp } diff --git a/android/bazel.go b/android/bazel.go index 9621f3ecd..ba29f6d0f 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -126,40 +126,21 @@ const ( ) var ( - // Do not write BUILD files for these directories - // NOTE: this is not recursive - bp2buildDoNotWriteBuildFileList = []string{ - // Don't generate these BUILD files - because external BUILD files already exist - "external/boringssl", - "external/brotli", - "external/dagger2", - "external/flatbuffers", - "external/gflags", - "external/google-fruit", - "external/grpc-grpc", - "external/grpc-grpc/test/core/util", - "external/grpc-grpc/test/cpp/common", - "external/grpc-grpc/third_party/address_sorting", - "external/nanopb-c", - "external/nos/host/generic", - "external/nos/host/generic/libnos", - "external/nos/host/generic/libnos/generator", - "external/nos/host/generic/libnos_datagram", - "external/nos/host/generic/libnos_transport", - "external/nos/host/generic/nugget/proto", - "external/perfetto", - "external/protobuf", - "external/rust/cxx", - "external/rust/cxx/demo", - "external/ruy", - "external/tensorflow", - "external/tensorflow/tensorflow/lite", - "external/tensorflow/tensorflow/lite/java", - "external/tensorflow/tensorflow/lite/kernels", - "external/tflite-support", - "external/tinyalsa_new", - "external/wycheproof", - "external/libyuv", + // Keep any existing BUILD files (and do not generate new BUILD files) for these directories + bp2buildKeepExistingBuildFile = map[string]bool{ + // This is actually build/bazel/build.BAZEL symlinked to ./BUILD + ".":/*recrusive = */ false, + + "build/bazel":/* recursive = */ true, + "build/pesto":/* recursive = */ true, + + // external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails + // e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed + "external/bazelbuild-rules_android":/* recursive = */ true, + + "prebuilts/clang/host/linux-x86":/* recursive = */ false, + "prebuilts/sdk":/* recursive = */ false, + "prebuilts/sdk/tools":/* recursive = */ false, } // Configure modules in these directories to enable bp2build_available: true or false by default. @@ -218,6 +199,7 @@ var ( // libcxx "libBionicBenchmarksUtils", // cc_library_static, fatal error: 'map' file not found, from libcxx "fmtlib", // cc_library_static, fatal error: 'cassert' file not found, from libcxx + "fmtlib_ndk", // cc_library_static, fatal error: 'cassert' file not found "libbase", // http://b/186826479, cc_library, fatal error: 'memory' file not found, from libcxx // http://b/186024507: Includes errors because of the system_shared_libs default value. @@ -229,6 +211,9 @@ var ( "note_memtag_heap_async", // http://b/185127353: cc_library_static, error: feature.h not found "note_memtag_heap_sync", // http://b/185127353: cc_library_static, error: feature.h not found + "libjemalloc5", // cc_library, ld.lld: error: undefined symbol: memset + "gwp_asan_crash_handler", // cc_library, ld.lld: error: undefined symbol: memset + // Tests. Handle later. "libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found "libjemalloc5_integrationtest", @@ -254,17 +239,12 @@ var ( } // Used for quicker lookups - bp2buildDoNotWriteBuildFile = map[string]bool{} bp2buildModuleDoNotConvert = map[string]bool{} bp2buildCcLibraryStaticOnly = map[string]bool{} mixedBuildsDisabled = map[string]bool{} ) func init() { - for _, moduleName := range bp2buildDoNotWriteBuildFileList { - bp2buildDoNotWriteBuildFile[moduleName] = true - } - for _, moduleName := range bp2buildModuleDoNotConvertList { bp2buildModuleDoNotConvert[moduleName] = true } @@ -282,12 +262,21 @@ func GenerateCcLibraryStaticOnly(ctx BazelConversionPathContext) bool { return bp2buildCcLibraryStaticOnly[ctx.Module().Name()] } -func ShouldWriteBuildFileForDir(dir string) bool { - if _, ok := bp2buildDoNotWriteBuildFile[dir]; ok { - return false - } else { +func ShouldKeepExistingBuildFileForDir(dir string) bool { + if _, ok := bp2buildKeepExistingBuildFile[dir]; ok { + // Exact dir match return true } + // Check if subtree match + for prefix, recursive := range bp2buildKeepExistingBuildFile { + if recursive { + if strings.HasPrefix(dir, prefix+"/") { + return true + } + } + } + // Default + return false } // MixedBuildsEnabled checks that a module is ready to be replaced by a diff --git a/bp2build/conversion.go b/bp2build/conversion.go index eb83b380f..101ad3d04 100644 --- a/bp2build/conversion.go +++ b/bp2build/conversion.go @@ -59,7 +59,7 @@ func CreateBazelFiles( func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { files := make([]BazelFile, 0, len(buildToTargets)) for _, dir := range android.SortedStringKeys(buildToTargets) { - if mode == Bp2Build && !android.ShouldWriteBuildFileForDir(dir) { + if mode == Bp2Build && android.ShouldKeepExistingBuildFileForDir(dir) { fmt.Printf("[bp2build] Not writing generated BUILD file for dir: '%s'\n", dir) continue } diff --git a/cc/bp2build.go b/cc/bp2build.go index 9f9143b37..33bb2699c 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -49,7 +49,7 @@ func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) { var allDeps []string - for _, p := range module.GetTargetProperties(&BaseLinkerProperties{}) { + for _, p := range module.GetTargetProperties(ctx, &BaseLinkerProperties{}) { // arch specific linker props if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok { allDeps = append(allDeps, baseLinkerProps.Header_libs...) @@ -273,7 +273,7 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul srcs.SetValueForArch(bazel.CONDITIONS_DEFAULT, defaultsSrcs) // Handle OS specific props. - for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) { + for os, props := range module.GetTargetProperties(ctx, &BaseCompilerProperties{}) { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { srcsList := parseSrcs(baseCompilerProps) // TODO(b/186153868): add support for os-specific srcs and exclude_srcs @@ -358,7 +358,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) } } - for os, p := range module.GetTargetProperties(&BaseLinkerProperties{}) { + for os, p := range module.GetTargetProperties(ctx, &BaseLinkerProperties{}) { if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok { libs := baseLinkerProps.Header_libs libs = append(libs, baseLinkerProps.Export_header_lib_headers...) @@ -434,7 +434,7 @@ func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Mo } } - for os, props := range module.GetTargetProperties(&FlagExporterProperties{}) { + for os, props := range module.GetTargetProperties(ctx, &FlagExporterProperties{}) { if flagExporterProperties, ok := props.(*FlagExporterProperties); ok { osIncludeDirs := flagExporterProperties.Export_system_include_dirs osIncludeDirs = append(osIncludeDirs, flagExporterProperties.Export_include_dirs...) diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 044689e67..70c88563f 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -17,6 +17,7 @@ package main import ( "flag" "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -357,6 +358,80 @@ func touch(path string) { } } +// Find BUILD files in the srcDir which... +// +// - are not on the allow list (android/bazel.go#ShouldKeepExistingBuildFileForDir()) +// +// - won't be overwritten by corresponding bp2build generated files +// +// And return their paths so they can be left out of the Bazel workspace dir (i.e. ignored) +func getPathsToIgnoredBuildFiles(topDir string, outDir string, generatedRoot string) ([]string, error) { + paths := make([]string, 0) + + err := filepath.WalkDir(topDir, func(fFullPath string, fDirEntry fs.DirEntry, err error) error { + if err != nil { + // Warn about error, but continue trying to walk the directory tree + fmt.Fprintf(os.Stderr, "WARNING: Error accessing path '%s', err: %s\n", fFullPath, err) + return nil + } + if fDirEntry.IsDir() { + // Don't ignore entire directories + return nil + } + if !(fDirEntry.Name() == "BUILD" || fDirEntry.Name() == "BUILD.bazel") { + // Don't ignore this file - it is not a build file + return nil + } + f := strings.TrimPrefix(fFullPath, topDir+"/") + if strings.HasPrefix(f, ".repo/") { + // Don't check for files to ignore in the .repo dir (recursively) + return fs.SkipDir + } + if strings.HasPrefix(f, outDir+"/") { + // Don't check for files to ignore in the out dir (recursively) + return fs.SkipDir + } + if strings.HasPrefix(f, generatedRoot) { + // Don't check for files to ignore in the bp2build dir (recursively) + // NOTE: This is usually under outDir + return fs.SkipDir + } + fDir := filepath.Dir(f) + if android.ShouldKeepExistingBuildFileForDir(fDir) { + // Don't ignore this existing build file + return nil + } + f_bp2build := shared.JoinPath(topDir, generatedRoot, f) + if _, err := os.Stat(f_bp2build); err == nil { + // If bp2build generated an alternate BUILD file, don't exclude this workspace path + // BUILD file clash resolution happens later in the symlink forest creation + return nil + } + fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", f) + paths = append(paths, f) + return nil + }) + + return paths, err +} + +// Returns temporary symlink forest excludes necessary for bazel build //external/... (and bazel build //frameworks/...) to work +func getTemporaryExcludes() []string { + excludes := make([]string, 0) + + // FIXME: 'autotest_lib' is a symlink back to external/autotest, and this causes an infinite symlink expansion error for Bazel + excludes = append(excludes, "external/autotest/venv/autotest_lib") + + // FIXME: The external/google-fruit/extras/bazel_root/third_party/fruit dir is poison + // It contains several symlinks back to real source dirs, and those source dirs contain BUILD files we want to ignore + excludes = append(excludes, "external/google-fruit/extras/bazel_root/third_party/fruit") + + // FIXME: 'frameworks/compile/slang' has a filegroup error due to an escaping issue + excludes = append(excludes, "frameworks/compile/slang") + + return excludes +} + // Run Soong in the bp2build mode. This creates a standalone context that registers // an alternate pipeline of mutators and singletons specifically for generating // Bazel BUILD files instead of Ninja files. @@ -415,6 +490,18 @@ func runBp2Build(configuration android.Config, extraNinjaDeps []string) { excludes = append(excludes, bootstrap.CmdlineArgs.NinjaBuildDir) } + // FIXME: Don't hardcode this here + topLevelOutDir := "out" + + pathsToIgnoredBuildFiles, err := getPathsToIgnoredBuildFiles(topDir, topLevelOutDir, generatedRoot) + if err != nil { + fmt.Fprintf(os.Stderr, "Error walking SrcDir: '%s': %s\n", configuration.SrcDir(), err) + os.Exit(1) + } + excludes = append(excludes, pathsToIgnoredBuildFiles...) + + excludes = append(excludes, getTemporaryExcludes()...) + symlinkForestDeps := bp2build.PlantSymlinkForest( topDir, workspaceRoot, generatedRoot, configuration.SrcDir(), excludes) diff --git a/rust/rust.go b/rust/rust.go index f068b3d7b..46c8f250c 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -619,6 +619,10 @@ func (mod *Module) CoverageFiles() android.Paths { } func (mod *Module) installable(apexInfo android.ApexInfo) bool { + if !mod.EverInstallable() { + return false + } + // The apex variant is not installable because it is included in the APEX and won't appear // in the system partition as a standalone file. if !apexInfo.IsForPlatform() { |