Adds integration test for cc_shared_library.

We use BUILD example added in previous CL and inspect the resulting *.so files with nm.

Also fixes implementation of shared library to work with Bazel after having flipped the legacy whole archive flag. This caused exported libraries to be dropped by the linker unless they were alwayslink.

Still more tests to come.

RELNOTES:none
PiperOrigin-RevId: 280640226
Change-Id: I34b48ce7379536352f87b703580083eb85ca67b3
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 138231a..612bb16 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -19,7 +19,7 @@
     - "//tools/migration:all"
     - "//tools/runfiles:all"
     test_flags:
-    - "--test_timeout=300"
+    - "--test_timeout=120"
     test_targets:
     - "//:all"
     - "//cc:all"
@@ -53,3 +53,8 @@
     - "//examples/test_cc_shared_library/..."
     build_flags:
     - "--experimental_cc_shared_library"
+    test_flags:
+    - "--test_timeout=120"
+    - "--experimental_cc_shared_library"
+    test_targets:
+    - "//examples/test_cc_shared_library/..."
diff --git a/examples/experimental_cc_shared_library.bzl b/examples/experimental_cc_shared_library.bzl
index 5d13a31..3e05583 100644
--- a/examples/experimental_cc_shared_library.bzl
+++ b/examples/experimental_cc_shared_library.bzl
@@ -80,13 +80,38 @@
             exports_map[str(export.label)] = linker_input
     return exports_map
 
-def _filter_inputs(ctx, transitive_exports):
+def _wrap_static_library_with_alwayslink(ctx, feature_configuration, cc_toolchain, linker_input):
+    new_libraries_to_link = []
+    for old_library_to_link in linker_input.libraries:
+        # TODO(#5200): This will lose the object files from a library to link.
+        # Not too bad for the prototype but as soon as the library_to_link
+        # constructor has object parameters this should be changed.
+        new_library_to_link = cc_common.create_library_to_link(
+            actions = ctx.actions,
+            feature_configuration = feature_configuration,
+            cc_toolchain = cc_toolchain,
+            static_library = old_library_to_link.static_library,
+            pic_static_library = old_library_to_link.pic_static_library,
+            alwayslink = True,
+        )
+        new_libraries_to_link.append(new_library_to_link)
+
+    return cc_common.create_linker_input(
+        owner = linker_input.owner,
+        libraries = depset(direct = new_libraries_to_link),
+        user_link_flags = depset(direct = linker_input.user_link_flags),
+        additional_inputs = depset(direct = linker_input.additional_inputs),
+    )
+
+def _filter_inputs(ctx, feature_configuration, cc_toolchain, transitive_exports):
     static_linker_inputs = []
     dynamic_linker_inputs = []
 
     graph_structure_aspect_nodes = []
     linker_inputs = []
+    direct_exports = {}
     for export in ctx.attr.exports:
+        direct_exports[str(export.label)] = True
         linker_inputs.extend(export[CcInfo].linking_context.linker_inputs.to_list())
         graph_structure_aspect_nodes.append(export[GraphNodeInfo])
 
@@ -102,8 +127,12 @@
     )
 
     already_linked_dynamically = {}
+    owners_seen = {}
     for linker_input in linker_inputs:
         owner = str(linker_input.owner)
+        if owner in owners_seen:
+            continue
+        owners_seen[owner] = True
         if owner in link_dynamically_labels:
             dynamic_linker_input = transitive_exports[owner]
             if str(dynamic_linker_input.owner) not in already_linked_dynamically:
@@ -114,7 +143,15 @@
             for linked_statically_by in link_statically_labels[owner]:
                 if linked_statically_by == str(ctx.label):
                     can_be_linked_statically = True
-                    static_linker_inputs.append(linker_input)
+                    static_linker_input = linker_input
+                    if owner in direct_exports:
+                        static_linker_input = _wrap_static_library_with_alwayslink(
+                            ctx,
+                            feature_configuration,
+                            cc_toolchain,
+                            linker_input,
+                        )
+                    static_linker_inputs.append(static_linker_input)
                     break
             if not can_be_linked_statically:
                 fail("We can't link " +
@@ -150,8 +187,14 @@
     exports_map = _build_exports_map_from_only_dynamic_deps(merged_cc_shared_library_info)
     for export in ctx.attr.exports:
         if str(export.label) in exports_map:
-            fail("Trying to export a library already exported by a different shared library: " + str(export.label))
-    (static_linker_inputs, dynamic_linker_inputs) = _filter_inputs(ctx, exports_map)
+            fail("Trying to export a library already exported by a different shared library: " +
+                 str(export.label))
+    (static_linker_inputs, dynamic_linker_inputs) = _filter_inputs(
+        ctx,
+        feature_configuration,
+        cc_toolchain,
+        exports_map,
+    )
 
     linking_context = _create_linker_context(ctx, static_linker_inputs, dynamic_linker_inputs)
 
@@ -175,8 +218,17 @@
         output_type = "dynamic_library",
     )
 
+    runfiles = ctx.runfiles(
+        files = [linking_outputs.library_to_link.resolved_symlink_dynamic_library],
+    )
+    for dep in ctx.attr.dynamic_deps:
+        runfiles = runfiles.merge(dep[DefaultInfo].data_runfiles)
+
     return [
-        DefaultInfo(files = depset([linking_outputs.library_to_link.resolved_symlink_dynamic_library])),
+        DefaultInfo(
+            files = depset([linking_outputs.library_to_link.resolved_symlink_dynamic_library]),
+            runfiles = runfiles,
+        ),
         CcSharedLibraryInfo(
             dynamic_deps = merged_cc_shared_library_info,
             exports = ctx.attr.exports,
diff --git a/examples/test_cc_shared_library/BUILD b/examples/test_cc_shared_library/BUILD
index 8034dc2..a1c4a5a 100644
--- a/examples/test_cc_shared_library/BUILD
+++ b/examples/test_cc_shared_library/BUILD
@@ -93,3 +93,12 @@
         "//examples/test_cc_shared_library:foo_so",
     ],
 )
+
+sh_test(
+    name = "cc_shared_library_integration_test",
+    srcs = ["cc_shared_library_integration_test.sh"],
+    data = [
+        ":bar_so",
+        ":foo_so",
+    ],
+)
diff --git a/examples/test_cc_shared_library/cc_shared_library_integration_test.sh b/examples/test_cc_shared_library/cc_shared_library_integration_test.sh
new file mode 100755
index 0000000..4acee3f
--- /dev/null
+++ b/examples/test_cc_shared_library/cc_shared_library_integration_test.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright 2019 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -euo pipefail
+
+function check_symbol_present() {
+  message="Should have seen '$2' but didn't."
+  echo "$1" | (grep -q "$2" || (echo "$message" && exit 1))
+}
+
+function check_symbol_absent() {
+  message="Shouldn't have seen '$2' but did."
+  if [ "$(echo $1 | grep -c $2)" -gt 0 ]; then
+    echo "$message"
+    exit 1
+  fi
+}
+
+function test_output {
+  foo_so=$(find . -name libfoo_so.so)
+  symbols=$(nm -D $foo_so)
+  check_symbol_present "$symbols" "U _Z3barv"
+  check_symbol_present "$symbols" "T _Z3bazv"
+  check_symbol_present "$symbols" "T _Z3foov"
+
+  check_symbol_absent "$symbols" "_Z3quxv"
+  check_symbol_absent "$symbols" "_Z4bar3v"
+  check_symbol_absent "$symbols" "_Z4bar4v"
+
+  exit 0
+}
+
+test_output