Sets SONAME on shared objects in Android binaries.

Adds a linker flag to set the internal DT_SONAME. This fixes #1578 for
SDK 24 and removes the warnings for previous SDKs. There is no need to
set the linker flag for android_librarys that depend on native code,
because the linker flag will be set by the android_binarys that depend
on that android_library.

--
Change-Id: If6422f2c2677ec974a3682e3038d7fe159ed4978
Reviewed-on: https://bazel-review.googlesource.com/#/c/4210/
MOS_MIGRATED_REVID=128833820
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 60c32e8..e08c261 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -69,12 +69,10 @@
 import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /**
@@ -860,22 +858,25 @@
   }
 
   public CcLinkParamsStore getCcLinkParamsStore() {
-    return getCcLinkParamsStore(javaCommon.targetsTreatedAsDeps(ClasspathType.BOTH));
+    return getCcLinkParamsStore(javaCommon.targetsTreatedAsDeps(ClasspathType.BOTH),
+        ImmutableList.<String>of());
   }
 
   public static CcLinkParamsStore getCcLinkParamsStore(
-      final Iterable<? extends TransitiveInfoCollection> deps) {
+      final Iterable<? extends TransitiveInfoCollection> deps, final Collection<String> linkOpts) {
     return new CcLinkParamsStore() {
       @Override
-      protected void collect(CcLinkParams.Builder builder, boolean linkingStatically,
-                             boolean linkShared) {
-        builder.addTransitiveTargets(deps,
+      protected void collect(
+          CcLinkParams.Builder builder, boolean linkingStatically, boolean linkShared) {
+        builder.addTransitiveTargets(
+            deps,
             // Link in Java-specific C++ code in the transitive closure
             JavaCcLinkParamsProvider.TO_LINK_PARAMS,
             // Link in Android-specific C++ code (e.g., android_libraries) in the transitive closure
             AndroidCcLinkParamsProvider.TO_LINK_PARAMS,
             // Link in non-language-specific C++ code in the transitive closure
             CcLinkParamsProvider.TO_LINK_PARAMS);
+        builder.addLinkOpts(linkOpts);
       }
     };
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
index fc736ae..7c3c8de 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
@@ -34,14 +34,12 @@
 import com.google.devtools.build.lib.rules.cpp.LinkerInput;
 import com.google.devtools.build.lib.rules.nativedeps.NativeDepsHelper;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
-
 import javax.annotation.Nullable;
 
 /** Represents the collection of native libraries (.so) to be installed in the APK. */
@@ -71,8 +69,11 @@
     Map<String, Iterable<Artifact>> result = new LinkedHashMap<>();
     for (Map.Entry<String, Collection<TransitiveInfoCollection>> entry :
         depsByArchitecture.asMap().entrySet()) {
-      CcLinkParams linkParams = AndroidCommon.getCcLinkParamsStore(entry.getValue())
-          .get(/* linkingStatically */ true, /* linkShared */ true);
+      CcLinkParams linkParams =
+          AndroidCommon.getCcLinkParamsStore(
+                  entry.getValue(),
+                  ImmutableList.of("-Wl,-soname=lib" + ruleContext.getLabel().getName()))
+              .get(/* linkingStatically */ true, /* linkShared */ true);
 
       Artifact nativeDepsLibrary = NativeDepsHelper.maybeCreateAndroidNativeDepsAction(
           ruleContext, linkParams, configurationMap.get(entry.getKey()),
diff --git a/src/test/shell/bazel/android/android_integration_test.sh b/src/test/shell/bazel/android/android_integration_test.sh
index 38162a3..76ebfe5 100755
--- a/src/test/shell/bazel/android/android_integration_test.sh
+++ b/src/test/shell/bazel/android/android_integration_test.sh
@@ -159,6 +159,18 @@
   assert_equals "11" "$num_sos"
 }
 
+function check_soname() {
+  # For an android_binary with name foo, readelf output format is
+  #  Tag        Type          Name/Value
+  # 0x00000010 (SONAME)       Library soname: [libfoo]
+  #
+  # If -Wl,soname= is not set, then SONAME will not appear in the output.
+  soname=$(readelf -d bazel-bin/java/bazel/_dx/bin/native_symlinks/x86/libbin.so \
+    | grep SONAME \
+    | awk '{print substr($5,2,length($5)-2)}')
+  assert_equals "libbin" "$soname"
+}
+
 function test_sdk_library_deps() {
   create_new_workspace
   setup_android_support
@@ -183,6 +195,7 @@
 
   bazel build -s //java/bazel:bin --fat_apk_cpu="$cpus" || fail "build failed"
   check_num_sos
+  check_soname
 }
 
 function test_android_binary_clang() {
@@ -202,6 +215,7 @@
       --android_compiler=clang3.8 \
       || fail "build failed"
   check_num_sos
+  check_soname
 }
 
 # ndk r10 and earlier