rust-bindgen: wrap to add required library compilation flags

The easy part is to add NIX_CFLAGS_COMPILE for "regular" libraries.
A bit more tricky is to add the required flags for libclang to find
libstdcxx. For this we parse arguments to bindgen to look for
-x c++ or -xc++ and if found add NIX_CXXSTDLIB_COMPILE to the arguments.
This variable is populated by a complex dance of setupHooks. We trigger
this by adding clang to propagatedBuildInputs. A more subtle way may
exist.
This commit is contained in:
Symphorien Gibol 2018-08-19 14:26:20 +02:00
parent 6afd19e699
commit 4c4fc2299c
2 changed files with 75 additions and 10 deletions

View File

@ -1,6 +1,4 @@
{ stdenv, fetchFromGitHub, rustPlatform, makeWrapper, llvmPackages }:
# Future work: Automatically communicate NIX_CFLAGS_COMPILE to bindgen's tests and the bindgen executable itself.
{ stdenv, fetchFromGitHub, fetchpatch, rustPlatform, clang, llvmPackages, rustfmt, writeScriptBin }:
rustPlatform.buildRustPackage rec {
name = "rust-bindgen-${version}";
@ -13,23 +11,54 @@ rustPlatform.buildRustPackage rec {
sha256 = "0cqjr7qspjrfgqcp4nqxljmhhbqyijb2jpw3lajgjj48y6wrnw93";
};
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ llvmPackages.clang-unwrapped.lib ];
cargoSha256 = "0b8v6c7q1abibzygrigldpd31lyd5ngmj4vq5d7zni96m20mm85w";
libclang = llvmPackages.libclang.lib; #for substituteAll
buildInputs = [ libclang ];
propagatedBuildInputs = [ clang ]; # to populate NIX_CXXSTDLIB_COMPILE
patches = [
# https://github.com/rust-lang-nursery/rust-bindgen/pull/1376
(fetchpatch {
url = https://github.com/rust-lang-nursery/rust-bindgen/commit/c8b5406f08af82a92bf8faf852c21ba941d9c176.patch;
sha256 = "16ibr2rplh0qz8rsq6gir45xlz5nasad4y8fprwhrb7ssv8wfkss";
})
];
configurePhase = ''
export LIBCLANG_PATH="${llvmPackages.clang-unwrapped.lib}/lib"
export LIBCLANG_PATH="${libclang}/lib"
'';
postInstall = ''
wrapProgram $out/bin/bindgen --set LIBCLANG_PATH "${llvmPackages.clang-unwrapped.lib}/lib"
mv $out/bin/{bindgen,.bindgen-wrapped};
substituteAll ${./wrapper.sh} $out/bin/bindgen
chmod +x $out/bin/bindgen
'';
cargoSha256 = "0b8v6c7q1abibzygrigldpd31lyd5ngmj4vq5d7zni96m20mm85w";
doCheck = false; # A test fails because it can't find standard headers in NixOS
doCheck = false; # half the tests fail because our rustfmt is not nightly enough
checkInputs =
let fakeRustup = writeScriptBin "rustup" ''
#!${stdenv.shell}
shift
shift
exec "$@"
'';
in [
rustfmt
fakeRustup # the test suite insists in calling `rustup run nightly rustfmt`
clang
];
meta = with stdenv.lib; {
description = "C and C++ binding generator";
longDescription = ''
Bindgen takes a c or c++ header file and turns them into
rust ffi declarations.
As with most compiler related software, this will only work
inside a nix-shell with the required libraries as buildInputs.
'';
homepage = https://github.com/rust-lang-nursery/rust-bindgen;
license = with licenses; [ bsd3 ];
maintainers = [ maintainers.ralith ];

View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
sep='--' # whether to add -- before new options
cxx=0 # whether cxx was explicitly requested
lastWasx=0 # whether the last argument passed was -x
for e in "$@"; do
if [[ "$e" == "--" ]]; then
sep=
fi;
if [[ "$sep" == "" ]]; then
# we look for -x c++ after -- only
if [[ "$e" == "-x" ]]; then
lastWasx=1
fi;
if [[ $lastWasx -eq 1 && "$e" == "c++" ]]; then
lastWasx=0
cxx=1
fi;
if [[ "$e" == "-xc++" || "$e" == -std=c++* ]]; then
cxx=1
fi;
fi;
done;
cxxflags=
if [[ $cxx -eq 1 ]]; then
cxxflags=$NIX_CXXSTDLIB_COMPILE
fi;
if [[ -n "$NIX_DEBUG" ]]; then
set -x;
fi;
export LIBCLANG_PATH="@libclang@/lib"
# shellcheck disable=SC2086
# cxxflags and NIX_CFLAGS_COMPILE should be word-split
exec -a "$0" @out@/bin/.bindgen-wrapped "$@" $sep $cxxflags $NIX_CFLAGS_COMPILE
# note that we add the flags after $@ which is incorrect. This is only for the sake
# of simplicity.