Add a check that dependencies don't include conflicting explicit versions
When manually specifying #impl dependencies it can get difficult to
debug issues when both libfoo and libfoo#impl are in the dependencies.
Add a check that the list of shared libraries doesn't include two
of the same library with different explicit versions.
Bug: 372543712
Test: TestCheckConflictingExplicitVersions
Flag: EXEMPT host only
Change-Id: I6863999259ba10381c3bdb8d5ac817736ca4601a
diff --git a/cc/cc.go b/cc/cc.go
index d187259..5480a8c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -19,8 +19,10 @@
// is handled in builder.go
import (
+ "errors"
"fmt"
"io"
+ "slices"
"strconv"
"strings"
@@ -2261,6 +2263,10 @@
deps.RuntimeLibs = android.LastUniqueStrings(deps.RuntimeLibs)
deps.LlndkHeaderLibs = android.LastUniqueStrings(deps.LlndkHeaderLibs)
+ if err := checkConflictingExplicitVersions(deps.SharedLibs); err != nil {
+ ctx.PropertyErrorf("shared_libs", "%s", err.Error())
+ }
+
for _, lib := range deps.ReexportSharedLibHeaders {
if !inList(lib, deps.SharedLibs) {
ctx.PropertyErrorf("export_shared_lib_headers", "Shared library not in shared_libs: '%s'", lib)
@@ -2288,6 +2294,26 @@
return deps
}
+func checkConflictingExplicitVersions(libs []string) error {
+ withoutVersion := func(s string) string {
+ name, _ := StubsLibNameAndVersion(s)
+ return name
+ }
+ var errs []error
+ for i, lib := range libs {
+ libName := withoutVersion(lib)
+ libsToCompare := libs[i+1:]
+ j := slices.IndexFunc(libsToCompare, func(s string) bool {
+ return withoutVersion(s) == libName
+ })
+ if j >= 0 {
+ errs = append(errs, fmt.Errorf("duplicate shared libraries with different explicit versions: %q and %q",
+ lib, libsToCompare[j]))
+ }
+ }
+ return errors.Join(errs...)
+}
+
func (c *Module) beginMutator(actx android.BottomUpMutatorContext) {
ctx := &baseModuleContext{
BaseModuleContext: actx,
diff --git a/cc/cc_test.go b/cc/cc_test.go
index e906706..22f7c9f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3321,3 +3321,20 @@
t.Errorf("expected %q in cflags, got %q", "-Xclang -verify", cFlags_cv)
}
}
+
+func TestCheckConflictingExplicitVersions(t *testing.T) {
+ PrepareForIntegrationTestWithCc.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `shared_libs: duplicate shared libraries with different explicit versions: "libbar" and "libbar#impl"`,
+ )).
+ RunTestWithBp(t, `
+ cc_library {
+ name: "libfoo",
+ shared_libs: ["libbar", "libbar#impl"],
+ }
+
+ cc_library {
+ name: "libbar",
+ }
+ `)
+}