Drop bindgen and specialize hash handling

Bindgen cannot handle functional C macros, and now `GENERATE_CMP`
is part of the include chain of `nix/hash.hh`, breaking everything.

For now, let's just drop bindgen and simplify things.
This commit is contained in:
Zhaofeng Li 2023-06-12 18:52:16 -06:00
parent 552120a68a
commit 5ca98fbaa8
13 changed files with 16 additions and 258 deletions

105
Cargo.lock generated
View file

@ -211,7 +211,6 @@ version = "0.1.0"
dependencies = [
"async-stream",
"base64 0.21.2",
"bindgen",
"bytes",
"cxx",
"cxx-build",
@ -820,29 +819,6 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bindgen"
version = "0.65.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.18",
"which",
]
[[package]]
name = "binstring"
version = "0.1.1"
@ -1001,15 +977,6 @@ dependencies = [
"jobserver",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -1032,17 +999,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "3.2.25"
@ -1840,12 +1796,6 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "group"
version = "0.13.0"
@ -2357,28 +2307,12 @@ dependencies = [
"spin 0.5.2",
]
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "libm"
version = "0.2.7"
@ -2731,12 +2665,6 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pem-rfc7468"
version = "0.6.0"
@ -2852,16 +2780,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "prettyplease"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1"
dependencies = [
"proc-macro2",
"syn 2.0.18",
]
[[package]]
name = "primeorder"
version = "0.13.1"
@ -3214,12 +3132,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.0"
@ -3704,12 +3616,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
@ -4658,17 +4564,6 @@ dependencies = [
"webpki",
]
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]]
name = "whoami"
version = "1.4.0"

View file

@ -43,7 +43,6 @@ serde_json = "1.0.96"
tokio-test = "0.4.2"
[build-dependencies]
bindgen = { version = "0.65.1", optional = true }
cxx-build = { version = "1.0", optional = true }
pkg-config = "0.3.27"
@ -53,7 +52,7 @@ default = [ "nix_store", "tokio" ]
# Native libnixstore bindings.
#
# When disabled, the native Rust portions of nix_store can still be used.
nix_store = [ "dep:cxx", "dep:bindgen", "dep:cxx-build" ]
nix_store = [ "dep:cxx", "dep:cxx-build" ]
# Tokio.
#

View file

@ -2,48 +2,9 @@
//!
//! We link against libnixstore to perform actions on the Nix Store.
#[cfg(feature = "nix_store")]
use bindgen::callbacks::{EnumVariantValue, ParseCallbacks};
fn main() {
#[cfg(feature = "nix_store")]
build_bridge();
#[cfg(feature = "nix_store")]
run_bindgen();
}
#[cfg(feature = "nix_store")]
#[derive(Debug)]
struct TransformNix;
#[cfg(feature = "nix_store")]
impl ParseCallbacks for TransformNix {
fn enum_variant_name(
&self,
enum_name: Option<&str>,
original_variant_name: &str,
_variant_value: EnumVariantValue,
) -> Option<String> {
match enum_name {
Some("HashType") => {
let t = match original_variant_name {
"htUnknown" => "Unknown",
"htMD5" => "Md5",
"htSHA1" => "Sha1",
"htSHA256" => "Sha256",
"htSHA512" => "Sha512",
x => panic!("Unknown hash type {} - Add it in build.rs", x),
};
Some(t.to_owned())
}
_ => None,
}
}
fn include_file(&self, filename: &str) {
println!("cargo:rerun-if-changed={}", filename);
}
}
#[cfg(feature = "nix_store")]
@ -57,38 +18,6 @@ fn build_bridge() {
.compile("nixbinding");
println!("cargo:rerun-if-changed=src/nix_store/bindings");
}
#[cfg(feature = "nix_store")]
fn run_bindgen() {
use std::env;
use std::path::PathBuf;
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let headers = vec!["src/nix_store/bindings/bindgen.hpp"];
let mut builder = bindgen::Builder::default()
.clang_arg("-std=c++17")
.clang_arg("-include")
.clang_arg("nix/config.h")
.opaque_type("std::.*")
.allowlist_type("nix::Hash")
.rustified_enum("nix::HashType")
.disable_name_namespacing()
.layout_tests(false)
.parse_callbacks(Box::new(TransformNix));
for header in headers {
builder = builder.header(header);
println!("cargo:rerun-if-changed={}", header);
}
let bindings = builder.generate().expect("Failed to generate Nix bindings");
bindings
.write_to_file(out_path.join("bindgen.rs"))
.expect("Failed to write bindings");
// the -l flags must be after -lnixbinding
pkg_config::Config::new()

View file

@ -9,9 +9,6 @@ use sha2::{Digest, Sha256};
use crate::error::AtticResult;
#[cfg(feature = "nix_store")]
use crate::nix_store::{FfiHash, FfiHashType};
/// A hash.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Hash {
@ -95,14 +92,6 @@ impl Hash {
fn to_base32(&self) -> String {
nix_base32::to_nix_base32(self.data())
}
#[cfg(feature = "nix_store")]
pub(super) fn from_ffi_hash(hash: FfiHash) -> AtticResult<Self> {
match hash.type_ {
FfiHashType::Sha256 => Ok(Self::Sha256(hash.hash[..32].try_into().unwrap())),
typ => Err(Error::UnsupportedHashAlgorithm(typ.as_str().to_owned()).into()),
}
}
}
impl<'de> Deserialize<'de> for Hash {

View file

@ -1,2 +0,0 @@
#include <nix/hash.hh>
#include <nix/store-api.hh>

View file

@ -1,37 +0,0 @@
//! Generated by `rust-bindgen`.
//!
//! We use `rust-bindgen` to generate bindings for a limited set of simpler
//! structures.
#![allow(
dead_code,
deref_nullptr,
improper_ctypes,
non_camel_case_types,
non_snake_case,
non_upper_case_globals
)]
include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
use crate::error::AtticResult;
use crate::hash::Hash as RustHash;
impl Hash {
/// Converts this into the native Rust version of this hash.
pub fn into_rust(self) -> AtticResult<RustHash> {
RustHash::from_ffi_hash(self)
}
}
impl HashType {
/// Returns the identifier of the hashing algorithm.
pub fn as_str(&self) -> &'static str {
match self {
Self::Md5 => "md5",
Self::Sha1 => "sha1",
Self::Sha256 => "sha256",
Self::Sha512 => "sha512",
}
}
}

View file

@ -1,30 +1,15 @@
//! `libnixstore` Bindings
mod bindgen;
use std::cell::UnsafeCell;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};
use cxx::{type_id, ExternType};
use futures::stream::{Stream, StreamExt};
use tokio::io::{AsyncWrite, AsyncWriteExt};
use crate::{AtticError, AtticResult};
pub use bindgen::{Hash as FfiHash, HashType as FfiHashType};
unsafe impl ExternType for FfiHash {
type Id = type_id!("nix::Hash");
type Kind = cxx::kind::Trivial;
}
unsafe impl ExternType for FfiHashType {
type Id = type_id!("nix::HashType");
type Kind = cxx::kind::Trivial;
}
// The C++ implementation takes care of concurrency
#[repr(transparent)]
pub struct FfiNixStore(UnsafeCell<cxx::UniquePtr<ffi::CNixStore>>);
@ -182,9 +167,6 @@ mod ffi {
unsafe extern "C++" {
include!("attic/src/nix_store/bindings/nix.hpp");
#[namespace = "nix"]
type Hash = super::FfiHash;
// =========
// CNixStore
// =========
@ -254,8 +236,8 @@ mod ffi {
/// Mid-level wrapper for the `nix::ValidPathInfo` struct.
type CPathInfo;
/// Returns the NAR hash of the store path.
fn nar_hash(self: Pin<&mut CPathInfo>) -> Hash;
/// Returns the SHA-256 hash of the store path.
fn nar_sha256_hash(self: Pin<&mut CPathInfo>) -> &[u8];
/// Returns the size of the NAR.
fn nar_size(self: Pin<&mut CPathInfo>) -> u64;

View file

@ -41,8 +41,14 @@ void RustSink::eof() {
CPathInfo::CPathInfo(nix::ref<const nix::ValidPathInfo> pi) : pi(pi) {}
nix::Hash CPathInfo::nar_hash() {
return this->pi->narHash;
RHashSlice CPathInfo::nar_sha256_hash() {
auto &hash = this->pi->narHash;
if (hash.type != nix::htSHA256) {
throw nix::Error("Only SHA-256 hashes are supported at the moment");
}
return RHashSlice(hash.hash, hash.hashSize);
}
uint64_t CPathInfo::nar_size() {

View file

@ -29,6 +29,7 @@ template<class T> using RSlice = rust::Slice<T>;
using RString = rust::String;
using RStr = rust::Str;
using RBasePathSlice = RSlice<const unsigned char>;
using RHashSlice = RSlice<const unsigned char>;
struct AsyncWriteSender;
@ -46,7 +47,7 @@ class CPathInfo {
nix::ref<const nix::ValidPathInfo> pi;
public:
CPathInfo(nix::ref<const nix::ValidPathInfo> pi);
nix::Hash nar_hash();
RHashSlice nar_sha256_hash();
uint64_t nar_size();
std::unique_ptr<std::vector<std::string>> sigs();
std::unique_ptr<std::vector<std::string>> references();

View file

@ -58,9 +58,6 @@ use serde::{de, Deserialize, Serialize};
use crate::error::{AtticError, AtticResult};
use crate::hash::Hash;
#[cfg(feature = "nix_store")]
pub use bindings::{FfiHash, FfiHashType};
#[cfg(feature = "nix_store")]
pub use nix_store::NixStore;

View file

@ -9,6 +9,7 @@ use tokio::task::spawn_blocking;
use super::bindings::{open_nix_store, AsyncWriteAdapter, FfiNixStore};
use super::{to_base_name, StorePath, ValidPathInfo};
use crate::hash::Hash;
use crate::error::AtticResult;
/// High-level wrapper for the Unix Domain Socket Nix Store.
@ -200,7 +201,7 @@ impl NixStore {
// FIXME: Make this more ergonomic and efficient
let nar_size = c_path_info.pin_mut().nar_size();
let nar_hash = c_path_info.pin_mut().nar_hash();
let nar_sha256_hash: [u8; 32] = c_path_info.pin_mut().nar_sha256_hash().try_into().unwrap();
let references = c_path_info
.pin_mut()
.references()
@ -224,7 +225,7 @@ impl NixStore {
Ok(ValidPathInfo {
path: store_path,
nar_size,
nar_hash: nar_hash.into_rust()?,
nar_hash: Hash::Sha256(nar_sha256_hash),
references,
sigs,
ca: if ca.is_empty() { None } else { Some(ca) },

View file

@ -32,7 +32,6 @@ let
};
nativeBuildInputs = [
rustPlatform.bindgenHook
pkg-config
installShellFiles
];

View file

@ -31,7 +31,6 @@ in rustPlatform.buildRustPackage rec {
};
nativeBuildInputs = [
rustPlatform.bindgenHook
pkg-config
installShellFiles
];