target.apex.exclude_[shared|static]_libs to cc_* modules

The property is used to exclude some shared and static libs when the
module is built for an APEX.

Bug: 166468760
Test: m
Change-Id: I0dcaa4ae94c01aa00dc5539c60d3054c57fd8824
diff --git a/apex/apex.go b/apex/apex.go
index 7ab7454..986246f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1681,6 +1681,19 @@
 							// Don't track further
 							return false
 						}
+
+						// If the dep is not considered to be in the same
+						// apex, don't add it to filesInfo so that it is not
+						// included in this APEX.
+						// TODO(jiyong): move this to at the top of the
+						// else-if clause for the indirect dependencies.
+						// Currently, that's impossible because we would
+						// like to record requiredNativeLibs even when
+						// DepIsInSameAPex is false.
+						if !am.DepIsInSameApex(ctx, am) {
+							return false
+						}
+
 						filesInfo = append(filesInfo, af)
 						return true // track transitive dependencies
 					}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0b67ef5..b6369d3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6237,6 +6237,55 @@
 	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherlib\n")
 }
 
+func TestExcludeDependency(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: ["myapex"],
+			shared_libs: ["mylib2"],
+			target: {
+				apex: {
+					exclude_shared_libs: ["mylib2"],
+				},
+			},
+		}
+
+		cc_library {
+			name: "mylib2",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	// Check if mylib is linked to mylib2 for the non-apex target
+	ldFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
+	ensureContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
+
+	// Make sure that the link doesn't occur for the apex target
+	ldFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+	ensureNotContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared_apex10000/mylib2.so")
+
+	// It shouldn't appear in the copy cmd as well.
+	copyCmds := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule").Args["copy_commands"]
+	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/cc/cc.go b/cc/cc.go
index b1c1264..5cd3b04 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -129,6 +129,9 @@
 	// Used for host bionic
 	LinkerFlagsFile string
 	DynamicLinker   string
+
+	// List of libs that need to be excluded for APEX variant
+	ExcludeLibsForApex []string
 }
 
 // PathDeps is a struct containing file paths to dependencies of a module.
@@ -572,6 +575,9 @@
 	staticUnwinder bool
 
 	makeSuffix string
+
+	// Whether or not this dependency has to be followed for the apex variants
+	excludeInApex bool
 }
 
 // header returns true if the libraryDependencyTag is tagging a header lib dependency.
@@ -1950,6 +1956,9 @@
 		if inList(lib, deps.ReexportStaticLibHeaders) {
 			depTag.reexportFlags = true
 		}
+		if inList(lib, deps.ExcludeLibsForApex) {
+			depTag.excludeInApex = true
+		}
 
 		if impl, ok := syspropImplLibraries[lib]; ok {
 			lib = impl
@@ -1987,6 +1996,9 @@
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag.reexportFlags = true
 		}
+		if inList(lib, deps.ExcludeLibsForApex) {
+			depTag.excludeInApex = true
+		}
 
 		if impl, ok := syspropImplLibraries[lib]; ok {
 			lib = impl
@@ -2416,6 +2428,10 @@
 				return
 			}
 
+			if !apexInfo.IsForPlatform() && libDepTag.excludeInApex {
+				return
+			}
+
 			depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
 
 			var ptr *android.Paths
@@ -2435,6 +2451,7 @@
 					}
 					return
 				}
+
 				sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
 				sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryImplementationStubsInfoProvider).(SharedLibraryImplementationStubsInfo)
 
@@ -3015,6 +3032,10 @@
 			// linked; the dependency is used only during the compilation phase.
 			return false
 		}
+
+		if isLibDepTag && libDepTag.excludeInApex {
+			return false
+		}
 	}
 	if depTag == stubImplDepTag || depTag == llndkImplDep {
 		// We don't track beyond LLNDK or from an implementation library to its stubs.
diff --git a/cc/linker.go b/cc/linker.go
index 9d4a643..7bc4105 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -174,6 +174,15 @@
 			// variants.
 			Shared_libs []string
 		}
+		Apex struct {
+			// list of shared libs that should not be used to build the apex variant of
+			// the C/C++ module.
+			Exclude_shared_libs []string
+
+			// list of static libs that should not be used to build the apex ramdisk
+			// variant of the C/C++ module.
+			Exclude_static_libs []string
+		}
 	}
 
 	// make android::build:GetBuildNumber() available containing the build ID.
@@ -240,6 +249,16 @@
 	deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Exclude_static_libs)
 	deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Exclude_static_libs)
 
+	// Record the libraries that need to be excluded when building for APEX. Unlike other
+	// target.*.exclude_* properties, SharedLibs and StaticLibs are not modified here because
+	// this module hasn't yet passed the apexMutator. Therefore, we can't tell whether this is
+	// an apex variant of not. Record the exclude list in the deps struct for now. The info is
+	// used to mark the dependency tag when adding dependencies to the deps. Then inside
+	// GenerateAndroidBuildActions, the marked dependencies are ignored (i.e. not used) for APEX
+	// variants.
+	deps.ExcludeLibsForApex = append(deps.ExcludeLibsForApex, linker.Properties.Target.Apex.Exclude_shared_libs...)
+	deps.ExcludeLibsForApex = append(deps.ExcludeLibsForApex, linker.Properties.Target.Apex.Exclude_static_libs...)
+
 	if Bool(linker.Properties.Use_version_lib) {
 		deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
 	}