Add SkipToTransitiveDepsTag interface for dependency tags
Consider this dependency graph: A --> B --> C And let's assume that B is built into A (e.g. static_libs), while B --> C is a runtime dependency (e.g. required). We want to install C (but not B of course) when A gets installed. However, before this change, it was not supported because the dependency A -> B was not tracked in computeInstallDeps. One had to explicitly add a A -> C dependency. This change fixes the problem by introducing the new interface SkipToTransitiveDepsTag. computeInstallDeps uses it to decide whether to take all install files and packaging specs or only those from transitive dependencies. In the above example, if the dependency A --> B implements the new interface and returns true, B's transitive dependencies (i.e. C) are added into A's transitive dependencies. B's outputs are not added. Bug: N/A Test: go test ./... under soong/android Change-Id: I3ca03a21633883f320ecb9e5bc82eb134519cd88
This commit is contained in:
@@ -44,6 +44,21 @@ func IsInstallDepNeededTag(tag blueprint.DependencyTag) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Dependency tags can implement this interface and return true from SkipToTransitiveDeps to
|
||||
// annotate that this dependency isn't installed, but its transitive dependencies are. This is
|
||||
// useful when a module is built into another module (ex: static linking) but the module still has
|
||||
// runtime dependencies.
|
||||
type SkipToTransitiveDepsTag interface {
|
||||
SkipToTransitiveDeps() bool
|
||||
}
|
||||
|
||||
func IsSkipToTransitiveDepsTag(tag blueprint.DependencyTag) bool {
|
||||
if i, ok := tag.(SkipToTransitiveDepsTag); ok {
|
||||
return i.SkipToTransitiveDeps()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PropagateAconfigValidationDependencyTag interface {
|
||||
PropagateAconfigValidation() bool
|
||||
}
|
||||
|
@@ -1470,15 +1470,27 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]*DepSet[InstallPat
|
||||
var installDeps []*DepSet[InstallPath]
|
||||
var packagingSpecs []*DepSet[PackagingSpec]
|
||||
ctx.VisitDirectDeps(func(dep Module) {
|
||||
if isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
|
||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||
// If this is true, the direct outputs from the module is not gathered, but its
|
||||
// transitive deps are still gathered.
|
||||
skipToTransitive := IsSkipToTransitiveDepsTag(depTag)
|
||||
if isInstallDepNeeded(dep, depTag) || skipToTransitive {
|
||||
// Installation is still handled by Make, so anything hidden from Make is not
|
||||
// installable.
|
||||
if !dep.IsHideFromMake() && !dep.IsSkipInstall() {
|
||||
installDeps = append(installDeps, dep.base().installFilesDepSet)
|
||||
if skipToTransitive {
|
||||
installDeps = append(installDeps, dep.base().installFilesDepSet.transitive...)
|
||||
} else {
|
||||
installDeps = append(installDeps, dep.base().installFilesDepSet)
|
||||
}
|
||||
}
|
||||
// Add packaging deps even when the dependency is not installed so that uninstallable
|
||||
// modules can still be packaged. Often the package will be installed instead.
|
||||
packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet)
|
||||
if skipToTransitive {
|
||||
packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet.transitive...)
|
||||
} else {
|
||||
packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@@ -25,8 +25,9 @@ import (
|
||||
type componentTestModule struct {
|
||||
ModuleBase
|
||||
props struct {
|
||||
Deps []string
|
||||
Skip_install *bool
|
||||
Deps []string
|
||||
Build_only_deps []string
|
||||
Skip_install *bool
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +37,18 @@ type installDepTag struct {
|
||||
InstallAlwaysNeededDependencyTag
|
||||
}
|
||||
|
||||
// dep tag for build_only_deps
|
||||
type buildOnlyDepTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
InstallAlwaysNeededDependencyTag
|
||||
}
|
||||
|
||||
var _ SkipToTransitiveDepsTag = (*buildOnlyDepTag)(nil)
|
||||
|
||||
func (tag buildOnlyDepTag) SkipToTransitiveDeps() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func componentTestModuleFactory() Module {
|
||||
m := &componentTestModule{}
|
||||
m.AddProperties(&m.props)
|
||||
@@ -45,6 +58,7 @@ func componentTestModuleFactory() Module {
|
||||
|
||||
func (m *componentTestModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||
ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
|
||||
ctx.AddDependency(ctx.Module(), buildOnlyDepTag{}, m.props.Build_only_deps...)
|
||||
}
|
||||
|
||||
func (m *componentTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
@@ -398,3 +412,30 @@ func TestPackagingWithSkipInstallDeps(t *testing.T) {
|
||||
}
|
||||
`, []string{"lib64/foo", "lib64/bar", "lib64/baz"})
|
||||
}
|
||||
|
||||
func TestPackagingWithSkipToTransitvDeps(t *testing.T) {
|
||||
// packag -[deps]-> foo -[build_only_deps]-> bar -[deps]-> baz
|
||||
// bar isn't installed, but it brings baz to its parent.
|
||||
multiTarget := false
|
||||
runPackagingTest(t, multiTarget,
|
||||
`
|
||||
component {
|
||||
name: "foo",
|
||||
build_only_deps: ["bar"],
|
||||
}
|
||||
|
||||
component {
|
||||
name: "bar",
|
||||
deps: ["baz"],
|
||||
}
|
||||
|
||||
component {
|
||||
name: "baz",
|
||||
}
|
||||
|
||||
package_module {
|
||||
name: "package",
|
||||
deps: ["foo"],
|
||||
}
|
||||
`, []string{"lib64/foo", "lib64/baz"})
|
||||
}
|
||||
|
Reference in New Issue
Block a user