Use the libraries included with the clang distribution for bindgen (#820)
* Use the libraries included with the clang distribution for bindgen
* Fall back to the system load path if libstdcxx is not specified
* Regenerate documentation
* Fix bugs and preserve backward compatibility with users of bindgen_clang_*
* Buildifier
* Regenerate documentation
* Re-enable tests
* Generate rpaths correctly
* Skip rpath generation on Windows
* Better comment about why test is disabled
* Add comment about DYLD_LIBRARY_PATH
* buildifier
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index eab4a50..a3a8ea0 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -29,10 +29,8 @@
- "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245
- "..."
- "@examples//..."
- # Skip tests for dylib support on osx, since we don't support it yet.
+ # This test requires --incompatible_macos_set_install_name and Bazel 4.2.0+
- "-@examples//ffi/rust_calling_c:matrix_dylib_test"
- - "-@examples//ffi/rust_calling_c:matrix_dynamically_linked"
- - "-@examples//ffi/rust_calling_c/simple/..."
build_targets: *osx_targets
test_targets: *osx_targets
build_flags:
diff --git a/bindgen/BUILD.bazel b/bindgen/BUILD.bazel
index 92543c9..2dc0b2d 100644
--- a/bindgen/BUILD.bazel
+++ b/bindgen/BUILD.bazel
@@ -19,10 +19,13 @@
"//conditions:default": "@bindgen_clang_linux//:clang",
}),
libclang = select({
- "//rust/platform:osx": "@bindgen_clang_osx//:libclang.so",
- "//conditions:default": "@bindgen_clang_linux//:libclang.so",
+ "//rust/platform:osx": "@bindgen_clang_osx//:libclang",
+ "//conditions:default": "@bindgen_clang_linux//:libclang",
}),
- libstdcxx = "@local_libstdcpp//:libstdc++",
+ libstdcxx = select({
+ "//rust/platform:osx": "@bindgen_clang_osx//:libc++",
+ "//conditions:default": None,
+ }),
)
toolchain(
diff --git a/bindgen/bindgen.bzl b/bindgen/bindgen.bzl
index d3f7266..2cb8d15 100644
--- a/bindgen/bindgen.bzl
+++ b/bindgen/bindgen.bzl
@@ -87,13 +87,6 @@
rustfmt_bin = toolchain.rustfmt or rust_toolchain.rustfmt
clang_bin = toolchain.clang
libclang = toolchain.libclang
-
- # TODO: This rule shouldn't need to depend on libstdc++
- # This rule requires an explicit dependency on a libstdc++ because
- # 1. It is a runtime dependency of libclang.so
- # 2. We cannot locate it in the cc_toolchain yet
- # Depending on how libclang.so was compiled, it may try to locate its libstdc++ dependency
- # in a way that makes our handling here unnecessary (eg. system /usr/lib/x86_64-linux-gnu/libstdc++.so.6)
libstdcxx = toolchain.libstdcxx
# rustfmt is not where bindgen expects to find it, so we format manually
@@ -130,8 +123,11 @@
"RUST_BACKTRACE": "1",
}
+ # Set the dynamic linker search path so that clang uses the libstdcxx from the toolchain.
+ # DYLD_LIBRARY_PATH is LD_LIBRARY_PATH on macOS.
if libstdcxx:
env["LD_LIBRARY_PATH"] = ":".join([f.dirname for f in _get_libs_for_static_executable(libstdcxx).to_list()])
+ env["DYLD_LIBRARY_PATH"] = env["LD_LIBRARY_PATH"]
ctx.actions.run(
executable = bindgen_bin,
@@ -140,9 +136,9 @@
transitive = [
cc_lib[CcInfo].compilation_context.headers,
_get_libs_for_static_executable(libclang),
- ] + [
+ ] + ([
_get_libs_for_static_executable(libstdcxx),
- ] if libstdcxx else [],
+ ] if libstdcxx else []),
),
outputs = [unformatted_output],
mnemonic = "RustBindgen",
@@ -232,9 +228,10 @@
providers = [CcInfo],
),
"libstdcxx": attr.label(
- doc = "A cc_library that satisfies libclang's libstdc++ dependency.",
+ doc = "A cc_library that satisfies libclang's libstdc++ dependency. This is used to make the execution of clang hermetic. If None, system libraries will be used instead.",
cfg = "exec",
providers = [CcInfo],
+ mandatory = False,
),
"rustfmt": attr.label(
doc = "The label of a `rustfmt` executable. If this is provided, generated sources will be formatted.",
diff --git a/bindgen/repositories.bzl b/bindgen/repositories.bzl
index c40b9c3..b9a1b2f 100644
--- a/bindgen/repositories.bzl
+++ b/bindgen/repositories.bzl
@@ -24,11 +24,6 @@
# nb. The bindgen rule itself should work on any platform.
_bindgen_clang_repositories()
- maybe(
- _local_libstdcpp,
- name = "local_libstdcpp",
- )
-
rules_rust_bindgen_fetch_remote_crates()
native.register_toolchains(str(Label("//bindgen:default_bindgen_toolchain")))
@@ -48,19 +43,29 @@
"""
_CLANG_BUILD_FILE = """\
-load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@rules_cc//cc:defs.bzl", "cc_import")
package(default_visibility = ["//visibility:public"])
sh_binary(
name = "clang",
srcs = ["bin/clang"],
- data = glob(["lib/**"]),
)
-cc_library(
+cc_import(
+ name = "libclang",
+ shared_library = "lib/libclang.{suffix}",
+)
+
+alias(
name = "libclang.so",
- srcs = ["{}"],
+ actual = ":libclang",
+ deprecation = "Use :libclang instead",
+)
+
+cc_import(
+ name = "libc++",
+ shared_library = "lib/libc++.{suffix}"
)
"""
@@ -72,7 +77,7 @@
urls = ["https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz"],
strip_prefix = "clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04",
sha256 = "b25f592a0c00686f03e3b7db68ca6dc87418f681f4ead4df4745a01d9be63843",
- build_file_content = _CLANG_BUILD_FILE.format("lib/libclang.so"),
+ build_file_content = _CLANG_BUILD_FILE.format(suffix = "so"),
workspace_file_content = _COMMON_WORKSPACE.format("bindgen_clang_linux"),
)
@@ -82,32 +87,6 @@
urls = ["https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz"],
strip_prefix = "clang+llvm-10.0.0-x86_64-apple-darwin",
sha256 = "633a833396bf2276094c126b072d52b59aca6249e7ce8eae14c728016edb5e61",
- build_file_content = _CLANG_BUILD_FILE.format("lib/libclang.dylib"),
+ build_file_content = _CLANG_BUILD_FILE.format(suffix = "dylib"),
workspace_file_content = _COMMON_WORKSPACE.format("bindgen_clang_osx"),
)
-
-_LIBSTDCPP_BUILD_FILE = """\
-load("@rules_cc//cc:defs.bzl", "cc_library")
-
-cc_library(
- name = "libstdc++",
- srcs = ["{}"],
- visibility = ["//visibility:public"]
-)
-"""
-
-def _local_libstdcpp_impl(repository_ctx):
- os = repository_ctx.os.name.lower()
- if os == "linux":
- repository_ctx.symlink("/usr/lib/x86_64-linux-gnu/libstdc++.so.6", "libstdc++.so.6")
- repository_ctx.file("BUILD.bazel", _LIBSTDCPP_BUILD_FILE.format("libstdc++.so.6"))
- elif os.startswith("mac"):
- repository_ctx.symlink("/usr/lib/libstdc++.6.dylib", "libstdc++.6.dylib")
- repository_ctx.file("BUILD.bazel", _LIBSTDCPP_BUILD_FILE.format("libstdc++.6.dylib"))
- else:
- fail(os + " is not supported.")
- repository_ctx.file("WORKSPACE.bazel", _COMMON_WORKSPACE.format(repository_ctx.name))
-
-_local_libstdcpp = repository_rule(
- implementation = _local_libstdcpp_impl,
-)
diff --git a/docs/flatten.md b/docs/flatten.md
index d6ae3a0..356b3f7 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -367,7 +367,7 @@
| <a id="rust_bindgen_toolchain-bindgen"></a>bindgen | The label of a <code>bindgen</code> executable. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-clang"></a>clang | The label of a <code>clang</code> executable. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-libclang"></a>libclang | A cc_library that provides bindgen's runtime dependency on libclang. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
-| <a id="rust_bindgen_toolchain-libstdcxx"></a>libstdcxx | A cc_library that satisfies libclang's libstdc++ dependency. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
+| <a id="rust_bindgen_toolchain-libstdcxx"></a>libstdcxx | A cc_library that satisfies libclang's libstdc++ dependency. This is used to make the execution of clang hermetic. If None, system libraries will be used instead. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-rustfmt"></a>rustfmt | The label of a <code>rustfmt</code> executable. If this is provided, generated sources will be formatted. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
diff --git a/docs/rust_bindgen.md b/docs/rust_bindgen.md
index e44c95b..c4b2f3f 100644
--- a/docs/rust_bindgen.md
+++ b/docs/rust_bindgen.md
@@ -47,7 +47,7 @@
| <a id="rust_bindgen_toolchain-bindgen"></a>bindgen | The label of a <code>bindgen</code> executable. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-clang"></a>clang | The label of a <code>clang</code> executable. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-libclang"></a>libclang | A cc_library that provides bindgen's runtime dependency on libclang. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
-| <a id="rust_bindgen_toolchain-libstdcxx"></a>libstdcxx | A cc_library that satisfies libclang's libstdc++ dependency. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
+| <a id="rust_bindgen_toolchain-libstdcxx"></a>libstdcxx | A cc_library that satisfies libclang's libstdc++ dependency. This is used to make the execution of clang hermetic. If None, system libraries will be used instead. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
| <a id="rust_bindgen_toolchain-rustfmt"></a>rustfmt | The label of a <code>rustfmt</code> executable. If this is provided, generated sources will be formatted. | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | optional | None |
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index dc154bf..9d1e28a 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -752,12 +752,17 @@
Returns:
depset: A set of relative paths from the output directory to each dependency
"""
- preferreds = [get_preferred_artifact(lib) for linker_input in dep_info.transitive_noncrates.to_list() for lib in linker_input.libraries]
- # TODO(augie): I don't understand why this can't just be filtering on
- # _is_dylib(lib), but doing that causes failures on darwin and windows
- # examples that otherwise work.
- dylibs = [lib for lib in preferreds if _has_dylib_ext(lib, toolchain.dylib_ext)]
+ # Windows has no rpath equivalent, so always return an empty depset.
+ if toolchain.os == "windows":
+ return depset([])
+
+ dylibs = [
+ get_preferred_artifact(lib)
+ for linker_input in dep_info.transitive_noncrates.to_list()
+ for lib in linker_input.libraries
+ if _is_dylib(lib)
+ ]
if not dylibs:
return depset([])