rust: avoid assuming a particular bindgen
build
`bindgen`'s logic to find `libclang` (via `clang-sys`) may change over time, and depends on how it was built (e.g. Linux distributions may decide to build it differently, and we are going to provide documentation on installing it via distributions later in this series). Therefore, clarify that `bindgen` may be built in several ways and simplify the documentation by only mentioning the most prominent environment variable (`LIBCLANG_PATH`) as an example on how to tweak the search of the library at runtime (i.e. when `bindgen` is built as our documentation explains). This also avoids duplicating the documentation, like `bindgen` itself does (i.e. it refers to `clang-sys`). Similarly, replace the test we had for this (which used the real program) with a mocked one, to avoid depending on the particular build as well. Tested-by: Benno Lossin <benno.lossin@proton.me> Tested-by: Andreas Hindborg <a.hindborg@samsung.com> Link: https://lore.kernel.org/r/20240709160615.998336-8-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
63b27f4a00
commit
d49082faf6
@ -113,20 +113,15 @@ Install it via (note that this will download and build the tool from source)::
|
|||||||
|
|
||||||
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
|
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
|
||||||
|
|
||||||
``bindgen`` needs to find a suitable ``libclang`` in order to work. If it is
|
``bindgen`` uses the ``clang-sys`` crate to find a suitable ``libclang`` (which
|
||||||
not found (or a different ``libclang`` than the one found should be used),
|
may be linked statically, dynamically or loaded at runtime). By default, the
|
||||||
the process can be tweaked using the environment variables understood by
|
``cargo`` command above will produce a ``bindgen`` binary that will load
|
||||||
``clang-sys`` (the Rust bindings crate that ``bindgen`` uses to access
|
``libclang`` at runtime. If it is not found (or a different ``libclang`` than
|
||||||
``libclang``):
|
the one found should be used), the process can be tweaked, e.g. by using the
|
||||||
|
``LIBCLANG_PATH`` environment variable. For details, please see ``clang-sys``'s
|
||||||
|
documentation at:
|
||||||
|
|
||||||
* ``LLVM_CONFIG_PATH`` can be pointed to an ``llvm-config`` executable.
|
https://github.com/KyleMayes/clang-sys#linking
|
||||||
|
|
||||||
* Or ``LIBCLANG_PATH`` can be pointed to a ``libclang`` shared library
|
|
||||||
or to the directory containing it.
|
|
||||||
|
|
||||||
* Or ``CLANG_PATH`` can be pointed to a ``clang`` executable.
|
|
||||||
|
|
||||||
For details, please see ``clang-sys``'s documentation at:
|
|
||||||
|
|
||||||
https://github.com/KyleMayes/clang-sys#environment-variables
|
https://github.com/KyleMayes/clang-sys#environment-variables
|
||||||
|
|
||||||
|
@ -55,10 +55,15 @@ else:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_bindgen(cls, version_stdout, libclang_stderr):
|
def generate_bindgen(cls, version_stdout, libclang_stderr):
|
||||||
|
if libclang_stderr is None:
|
||||||
|
libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
|
||||||
|
else:
|
||||||
|
libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
|
||||||
|
|
||||||
return cls.generate_executable(f"""#!/usr/bin/env python3
|
return cls.generate_executable(f"""#!/usr/bin/env python3
|
||||||
import sys
|
import sys
|
||||||
if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
|
if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
|
||||||
print({repr(libclang_stderr)}, file=sys.stderr)
|
{libclang_case}
|
||||||
else:
|
else:
|
||||||
print({repr(version_stdout)})
|
print({repr(version_stdout)})
|
||||||
""")
|
""")
|
||||||
@ -67,6 +72,10 @@ else:
|
|||||||
def generate_bindgen_version(cls, stdout):
|
def generate_bindgen_version(cls, stdout):
|
||||||
return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr)
|
return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_bindgen_libclang_failure(cls):
|
||||||
|
return cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_bindgen_libclang(cls, stderr):
|
def generate_bindgen_libclang(cls, stderr):
|
||||||
return cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, stderr)
|
return cls.generate_bindgen(cls.bindgen_default_bindgen_version_stdout, stderr)
|
||||||
@ -89,6 +98,7 @@ else:
|
|||||||
cls.rust_default_sysroot = subprocess.check_output(("rustc", "--print", "sysroot")).decode().strip()
|
cls.rust_default_sysroot = subprocess.check_output(("rustc", "--print", "sysroot")).decode().strip()
|
||||||
|
|
||||||
cls.bindgen_default_bindgen_version_stdout = f"bindgen {cls.bindgen_default_version}"
|
cls.bindgen_default_bindgen_version_stdout = f"bindgen {cls.bindgen_default_version}"
|
||||||
|
cls.bindgen_default_bindgen_libclang_failure_exit_code = 42
|
||||||
cls.bindgen_default_bindgen_libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {cls.llvm_default_version} [-W#pragma-messages], err: false"
|
cls.bindgen_default_bindgen_libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {cls.llvm_default_version} [-W#pragma-messages], err: false"
|
||||||
|
|
||||||
cls.default_rustc = cls.generate_rustc(f"rustc {cls.rustc_default_version}")
|
cls.default_rustc = cls.generate_rustc(f"rustc {cls.rustc_default_version}")
|
||||||
@ -227,15 +237,10 @@ else:
|
|||||||
self.assertIn(f"Rust bindings generator '{bindgen}' is too new. This may or may not work.", result.stderr)
|
self.assertIn(f"Rust bindings generator '{bindgen}' is too new. This may or may not work.", result.stderr)
|
||||||
|
|
||||||
def test_bindgen_libclang_failure(self):
|
def test_bindgen_libclang_failure(self):
|
||||||
for env in (
|
bindgen = self.generate_bindgen_libclang_failure()
|
||||||
{ "LLVM_CONFIG_PATH": self.missing },
|
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
|
||||||
{ "LIBCLANG_PATH": self.missing },
|
self.assertIn(f"Running '{bindgen}' to check the libclang version (used by the Rust", result.stderr)
|
||||||
{ "CLANG_PATH": self.missing },
|
self.assertIn(f"bindings generator) failed with code {self.bindgen_default_bindgen_libclang_failure_exit_code}. This may be caused by", result.stderr)
|
||||||
):
|
|
||||||
with self.subTest(env=env):
|
|
||||||
result = self.run_script(self.Expected.FAILURE, env | { "PATH": os.environ["PATH"], "BINDGEN": "bindgen" })
|
|
||||||
self.assertIn("Running 'bindgen' to check the libclang version (used by the Rust", result.stderr)
|
|
||||||
self.assertIn("bindings generator) failed with code ", result.stderr)
|
|
||||||
|
|
||||||
def test_bindgen_libclang_unexpected_version(self):
|
def test_bindgen_libclang_unexpected_version(self):
|
||||||
bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version unexpected [-W#pragma-messages], err: false")
|
bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version unexpected [-W#pragma-messages], err: false")
|
||||||
|
Loading…
Reference in New Issue
Block a user