TransitionMutators will need access to the original *mutatorInfo,
store it in mutatorContext instead of the name, and update all
accesses to the name to go through the *mutatorInfo.
Bug: 319288033
Test: go test ./...
Change-Id: I4bb1a17f44e55b23dd70708c9a5fde2ae80ce154
Creating variants has an optimization to reuse the logicModule of the
original variant as the logicModule of the first new variant. Using
the same logicModule meant that updating the Context.moduleInfo map
from logicModules to *moduleInfo would overwrite the old entry for
the original variant with the new entry for the first variant.
TransitionMutators will need to keep the original logicModule for
later use, which will require disabling the optimization that reuses
it. When the first variant is added to the map it no longer overwrites
the original variant. Excplicitly track the original logicModule and
remove it from the map if necessary.
Bug: 319288033
Test: go test ./...
Change-Id: I05ffdf6d7ce60508f6d9e9657c21032f2c4f5d9c
When splitting a module into variants the original *moduleInfo was
left in place but with logicModule set to nil as a marker that the
variant was obsolete and any incoming dependencies needed to be resolved
onto one of the newly split variants. A change to allow TransitionMutator
IncomingTransition calls when adding dependencies later will require
keeping the obsolete *moduleInfo and logicModule around so that
IncomingTransition can be called on it. so use an explicit boolean
to mark the module as obsolete instead of clearing logicModule.
Bug: 319288033
Test: go test ./...
Change-Id: I5dc201f43442aa07ac1b858240c675bab3782b55
Allow TransitionMutator OutgoingTransition and IncomingTransition
methods to access Providers from the current and dependency module
respectively.
Bug: 319288033
Test: none
Change-Id: If16ee7980ee0b8f4abaf3c112738fca3f13ab61c
TransitionMutators were calling OutgoingTransition and IncomingTransition
twice, once to determine all the necessary variations for each module,
and then again when creating the variations to resolve dependencies.
Store the final variation needed for each dependency during the first
computation, and use it to resolve the dependency variation in the second
pass.
Bug: 319288033
Test: all soong tests
Change-Id: I2e42c0d69efbfcff915267c484c18554b857e0b6
ctx.ModuleErrorf for the main blueprint config object doesn't
report an error, it just returns it.
If go had something like C++'s `[[nodiscard]]` or rust's `#[must_use]`
that would be useful here, but the issue has been open since 2017:
https://github.com/golang/go/issues/20803
Test: Presubmits
Change-Id: I72709e6c5466d55f5c0f3fe51a25c29df0826271
Bug: 323382414
Test: go tests, and I also ran both the old/new bpfmts on the whole aosp source tree, and the only difference between the results was one extra removed line in external/uwb
Change-Id: I4942c9247a66f1de5028de39caa5cd34b66093c3
To make it easier to handle the result of
Configurable[[]string].Evaluate()
Bug: 329711542
Test: go tests
Change-Id: I7364170564b1049a33873424c6da4fc26aff305b
Select statements are a new blueprint feature inspired by bazel's select
statements. They are essentially alternative syntax for soong config
variables that require less boilerplate. In addition, they support
making decisions based on a module's variant, which will eliminate
the need for manual property struct manipulation, such as the arch
mutator's arch: and target: properties.
In order to support decisions based on the variant, select statements
cannot be evaluated as soon as they're parsed. Instead, they must be
stored in the property struct unevaluated. This means that individual
properties need to change their type from say, string, to
Configurable[string]. Currently, only configurable strings, bools, and
string slices are supported, but more types can be added later.
The module implementation must call my_property.Evaluate(ctx) in order
to get the final, resolved value of the select statement.
Bug: 323382414
Test: go tests
Change-Id: I62f8721d7f0ac3d1df4a06d7eaa260a5aa7fcba3
It's not super useful because of Go's stupid restriction on not letting
you reflect private fields.
Test: m nothing
Change-Id: I1f73f06f5e64eaf4adce58a667b98b131aede53f
The property squashing functions were performing 19% of all allocations
and allocating 3.43 GB, most of which was used to track the name of the
property, but the name of the property is only used to print errors.
Keep the elements of the name in a preallocated slice instead, and only
compute the name when an error occurs.
Calling reflect.Value.Interface() was also expensive, and only passed
to filter and order functions, none of which use the values. Modify
the signature of the filter and order functions to remove the interfaces
and the property name.
Test: extend_test.go
Change-Id: I517f89daf251bb43f7cfefa6f1e83951c0e271b7
blueprint.variationMap.Equal was responsible for 11.5% of allocations
and 2.2% of allocated memory. reflect.DeepEquals is an expensive way
to compare a map. variationMap.subsetOf is already iterating through
the elements of the map to compare them, replace equal with a check that
the maps are the same length and then reuse subsetOf to check that the
have the same keys and values.
Test: SOONG_PROFILE_MEM=/tmp/mem.pprof m nothing
Change-Id: Ifb7cdf612e5455fd2f412488b7f94416c4e70c54
maphash.Hash implements WriteString, which avoids an allocation in
order to convert the string to a byte slice. Using the concrete
type instead of the io.Writer interface also allows int64Array to
be allocated on the stack.
Test: SOONG_PROFILE_MEM=/tmp/mem.pprof m nothing
Change-Id: I5894f7399c2a232f5f67d7d0724a6115ba2c278f
keyForPhonyCandidate was using sha256, which is a crypto hash and
unnecessarily expensive for this use case. hash/maphash would be
much faster because it implements WriteString and so doesn't cause
an extra allocation to copy to a byte slice for every write, but it
insists on randomizing the seed, which makes it unsuitable for writing
to the build.ninja file. Use hash/fnv instead, and use unsafe to
write strings to the hash to avoid the extra allocation.
Also replace the manually rolled parallelism with the existing
parallelVisit, which will reuse goroutines and limit the parallelism
to a useful value.
The hash could collide, and using a 64-bit hash makes that more
likely, so also check the full contents to make sure they are really
equal.
Cuts 1 second off Soong analysis time.
Test: SOONG_PROFILE_MEM=/tmp/mem.pprof m nothing
Change-Id: I4d1292cb158cfc5823a0f4d8b4aeac1d0b10230e
When setProvider() is called, hash the provider and store the hash in
the module. Then after the build is done, hash all the providers again
and compare the hashes. It's an error if they don't match.
Also add a flag to control it in case this check gets slow as we convert
more things to providers. However right now it's fast (unnoticable
in terms of whole seconds) so just have the flag always enabled.
Bug: 322069292
Test: m nothing
Change-Id: Ie4e806a6a9f20542ffcc7439eef376d3fb6a98ca
The description of TransitionMutators says that "the outgoing transition
should not take the properties of the dependency into account, only those
of the module that depends on it. For this reason, the dependency is not
even passed into it as an argument." However, OutgoingTransitionContext
was returing the dependency from ctx.Module(), not the parent. This
didn't matter for the only existing TransitionMutator, as it only used
the module to get a constant value.
Test: sanitize_test.go
Change-Id: I1ce5b3144787f57be4d50e95f0c923da9b2b079f
symlink_outputs was added so bazel could run ninja files, but we
abanoned that approach in roboleaf, and then roboleaf was cancelled
entirely. Remove this feature so we're more compatible with upstream
ninja / n2.
Bug: 160568334
Test: Presubmits
Change-Id: Ie3afd084c5574444dddac77cba1866e82ff2ca19
Force a resort of the module groups before running singletons
so that two singletons running in parallel don't cause a data
race when they trigger a resort in VisitAllModules.
Test: go test -race ./...
Change-Id: Iec041cec08c33c56787aadbde6a1b2b619815142
memoizeFullName was added to variables, rules and pools as an
optimization to prevent recomputing the full name repeatedly,
but the storage of variables, rules and pools are generally global
and not tied to the Context. When running multiple tests in
parallel there will be multiple Context objects all trying to
update the memoized names on the global variables, causing a data
race.
Package names were previously memoized via a pkgNames map stored
on the Context. Expand pkgNames to a nameTracker object that
contains maps for packages, variables, rules and pools, and replace
calls to fullName with calls through nameTracker.
Test: context_test.go
Change-Id: I15040b85a6d1dab9ab3cff44f227b22985acee18
When property a.b.c is not used, (also there is no a.* or a.b.* used)
"a", "a.b" and "a.b.c" are all in unusedNames.
removeUnnecessaryUnusedNames only keeps the last "a.b.c" as the
real unused name.
Test: TestNonExistentPropertyInSoongConfigModule, unpack_test.go and CI
Bug: 171232169
Change-Id: I861fa6933e558b07694ee5ff40ef549117d115ff