Merge pull request #28 from nixops4/better-conditional-compilation-and-maintenance
Better conditional compilation and some dev maintenance
This commit is contained in:
commit
654addc555
8 changed files with 136 additions and 62 deletions
|
|
@ -81,6 +81,9 @@
|
||||||
config.packages.nix
|
config.packages.nix
|
||||||
];
|
];
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
pkgs.pre-commit
|
||||||
|
config.treefmt.build.wrapper
|
||||||
|
|
||||||
pkgs.rust-analyzer
|
pkgs.rust-analyzer
|
||||||
pkgs.nixfmt-rfc-style
|
pkgs.nixfmt-rfc-style
|
||||||
pkgs.rustfmt
|
pkgs.rustfmt
|
||||||
|
|
@ -96,7 +99,6 @@
|
||||||
];
|
];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
${config.pre-commit.installationScript}
|
${config.pre-commit.installationScript}
|
||||||
source ${../bindgen-gcc.sh}
|
|
||||||
echo 1>&2 "Welcome to the development shell!"
|
echo 1>&2 "Welcome to the development shell!"
|
||||||
'';
|
'';
|
||||||
# rust-analyzer needs a NIX_PATH for some reason
|
# rust-analyzer needs a NIX_PATH for some reason
|
||||||
|
|
|
||||||
30
flake.lock
generated
30
flake.lock
generated
|
|
@ -27,11 +27,11 @@
|
||||||
"pyproject-nix": "pyproject-nix"
|
"pyproject-nix": "pyproject-nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764021028,
|
"lastModified": 1765228272,
|
||||||
"narHash": "sha256-4OlkDA0yJyqt5iTX9NqtHNghvkWNzYqmtX7FxDmEXt4=",
|
"narHash": "sha256-duTz4J4NP1edl/ZBdwZPduPM8j6g0yzjb8YH91T9vU0=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "dream2nix",
|
"repo": "dream2nix",
|
||||||
"rev": "ee20942e4524d3458a91108716c847a2d4299d2e",
|
"rev": "83c430ce6b6aedf149c5259f066bfff808722dbd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -170,11 +170,11 @@
|
||||||
"nixpkgs-regression": "nixpkgs-regression"
|
"nixpkgs-regression": "nixpkgs-regression"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764979397,
|
"lastModified": 1765241125,
|
||||||
"narHash": "sha256-oMSKV0NFQpfwYQ4wcIIDuH+0AwCQl+bYRgPznx38i8k=",
|
"narHash": "sha256-/Rr90FVpncaSWprG6+4t5VXHgDKDvFitzJPpdZgo+8I=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "525755dadc153c68e5ada8d287ab19af26383fff",
|
"rev": "7448aedd74e28174bfa33aad0d148c0070c86dfb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -196,11 +196,11 @@
|
||||||
"treefmt": "treefmt"
|
"treefmt": "treefmt"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1765001919,
|
"lastModified": 1765261286,
|
||||||
"narHash": "sha256-S5k0HAxjq2sbf5BC5DOly66joE08HfiyEJD8v2U3yLc=",
|
"narHash": "sha256-Ll29VFrT+VpnP4HG5LiL33IXuiz6cF2WfTwXONwMj7E=",
|
||||||
"owner": "yusdacra",
|
"owner": "yusdacra",
|
||||||
"repo": "nix-cargo-integration",
|
"repo": "nix-cargo-integration",
|
||||||
"rev": "0feff946314851edc88b9c783ad7d2dccd49abcc",
|
"rev": "92639295bbe953e4c8c32cbffa32dcb0a441118b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -211,11 +211,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764950072,
|
"lastModified": 1765186076,
|
||||||
"narHash": "sha256-BmPWzogsG2GsXZtlT+MTcAWeDK5hkbGRZTeZNW42fwA=",
|
"narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f61125a668a320878494449750330ca58b78c557",
|
"rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -355,11 +355,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1764988672,
|
"lastModified": 1765248027,
|
||||||
"narHash": "sha256-FIJtt3Zil89/hLy9i7f0R2xXcJDPc3CeqiiCLfsFV0Y=",
|
"narHash": "sha256-ngar+yP06x3+2k2Iey29uU0DWx5ur06h3iPBQXlU+yI=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "086fd19a68e80fcc8a298e9df4674982e4c498a6",
|
"rev": "7b50ad68415ae5be7ee4cc68fa570c420741b644",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,5 @@ tempfile = "3.10"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
pkg-config = "0.3"
|
pkg-config = "0.3"
|
||||||
|
# Needed for version parsing in build.rs
|
||||||
|
nix-bindings-util = { path = "../nix-bindings-util" }
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,6 @@
|
||||||
|
use nix_bindings_util::nix_version::emit_version_cfg;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Get nix version
|
|
||||||
let nix_version = pkg_config::probe_library("nix-store-c").unwrap().version;
|
let nix_version = pkg_config::probe_library("nix-store-c").unwrap().version;
|
||||||
|
emit_version_cfg(&nix_version, &["2.26", "2.33.0pre", "2.33"]);
|
||||||
// Generate version flags
|
|
||||||
// Unfortunately, Rust doesn't give us a "greater than" operator in conditional
|
|
||||||
// compilation, so we pre-evaluate the version comparisons here, making use
|
|
||||||
// of the multi-valued nature of Rust cfgs.
|
|
||||||
let relevant_versions = vec!["2.26", "2.33"];
|
|
||||||
let versions = relevant_versions
|
|
||||||
.iter()
|
|
||||||
.map(|v| format!("\"{}\"", v))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(",");
|
|
||||||
|
|
||||||
// Declare the known versions, so that Rust can warn about unknown versions
|
|
||||||
// that aren't part of `relevant_versions` yet - feel free to add entries.
|
|
||||||
println!(
|
|
||||||
"cargo:rustc-check-cfg=cfg(nix_at_least,values({}))",
|
|
||||||
versions
|
|
||||||
);
|
|
||||||
|
|
||||||
let nix_version = nix_version.split('.').collect::<Vec<&str>>();
|
|
||||||
let nix_version = (
|
|
||||||
nix_version[0].parse::<u32>().unwrap(),
|
|
||||||
nix_version[1].parse::<u32>().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
for version_str in relevant_versions {
|
|
||||||
let version = version_str.split('.').collect::<Vec<&str>>();
|
|
||||||
let version = (
|
|
||||||
version[0].parse::<u32>().unwrap(),
|
|
||||||
version[1].parse::<u32>().unwrap(),
|
|
||||||
);
|
|
||||||
if nix_version >= version {
|
|
||||||
println!("cargo:rustc-cfg=nix_at_least=\"{}\"", version_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#![cfg(nix_at_least = "2.33")]
|
#![cfg(nix_at_least = "2.33.0pre")]
|
||||||
|
|
||||||
use nix_bindings_bindgen_raw as raw;
|
use nix_bindings_bindgen_raw as raw;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use nix_bindings_util::string_return::{
|
||||||
callback_get_result_string, callback_get_result_string_data,
|
callback_get_result_string, callback_get_result_string_data,
|
||||||
};
|
};
|
||||||
use nix_bindings_util::{check_call, result_string_init};
|
use nix_bindings_util::{check_call, result_string_init};
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::{c_char, CString};
|
use std::ffi::{c_char, CString};
|
||||||
|
|
@ -14,7 +14,7 @@ use std::ptr::null_mut;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
use crate::derivation::Derivation;
|
use crate::derivation::Derivation;
|
||||||
use crate::path::StorePath;
|
use crate::path::StorePath;
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ lazy_static! {
|
||||||
static ref STORE_CACHE: Arc<Mutex<StoreCacheMap>> = Arc::new(Mutex::new(HashMap::new()));
|
static ref STORE_CACHE: Arc<Mutex<StoreCacheMap>> = Arc::new(Mutex::new(HashMap::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
unsafe extern "C" fn callback_get_result_store_path_set(
|
unsafe extern "C" fn callback_get_result_store_path_set(
|
||||||
_context: *mut raw::c_context,
|
_context: *mut raw::c_context,
|
||||||
user_data: *mut std::os::raw::c_void,
|
user_data: *mut std::os::raw::c_void,
|
||||||
|
|
@ -88,7 +88,7 @@ unsafe extern "C" fn callback_get_result_store_path_set(
|
||||||
ret.push(store_path);
|
ret.push(store_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
fn callback_get_result_store_path_set_data(vec: &mut Vec<StorePath>) -> *mut std::os::raw::c_void {
|
fn callback_get_result_store_path_set_data(vec: &mut Vec<StorePath>) -> *mut std::os::raw::c_void {
|
||||||
vec as *mut Vec<StorePath> as *mut std::os::raw::c_void
|
vec as *mut Vec<StorePath> as *mut std::os::raw::c_void
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +274,7 @@ impl Store {
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A [`Derivation`] object if parsing succeeds, or an error if the JSON is invalid
|
/// A [`Derivation`] object if parsing succeeds, or an error if the JSON is invalid
|
||||||
/// or malformed.
|
/// or malformed.
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
#[doc(alias = "nix_derivation_from_json")]
|
#[doc(alias = "nix_derivation_from_json")]
|
||||||
pub fn derivation_from_json(&mut self, json: &str) -> Result<Derivation> {
|
pub fn derivation_from_json(&mut self, json: &str) -> Result<Derivation> {
|
||||||
let json_cstr = CString::new(json)?;
|
let json_cstr = CString::new(json)?;
|
||||||
|
|
@ -302,7 +302,7 @@ impl Store {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The store path of the derivation (ending in `.drv`).
|
/// The store path of the derivation (ending in `.drv`).
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
#[doc(alias = "nix_add_derivation")]
|
#[doc(alias = "nix_add_derivation")]
|
||||||
pub fn add_derivation(&mut self, drv: &Derivation) -> Result<StorePath> {
|
pub fn add_derivation(&mut self, drv: &Derivation) -> Result<StorePath> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -331,7 +331,7 @@ impl Store {
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A [`BTreeMap`] mapping output names (e.g., "out", "dev", "doc") to their store paths.
|
/// A [`BTreeMap`] mapping output names (e.g., "out", "dev", "doc") to their store paths.
|
||||||
/// The map is ordered alphabetically by output name for deterministic iteration.
|
/// The map is ordered alphabetically by output name for deterministic iteration.
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
#[doc(alias = "nix_store_realise")]
|
#[doc(alias = "nix_store_realise")]
|
||||||
pub fn realise(&mut self, path: &StorePath) -> Result<BTreeMap<String, StorePath>> {
|
pub fn realise(&mut self, path: &StorePath) -> Result<BTreeMap<String, StorePath>> {
|
||||||
let mut outputs = BTreeMap::new();
|
let mut outputs = BTreeMap::new();
|
||||||
|
|
@ -388,7 +388,7 @@ impl Store {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A vector of store paths in the closure, in no particular order.
|
/// A vector of store paths in the closure, in no particular order.
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
#[doc(alias = "nix_store_get_fs_closure")]
|
#[doc(alias = "nix_store_get_fs_closure")]
|
||||||
pub fn get_fs_closure(
|
pub fn get_fs_closure(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -544,6 +544,7 @@ mod tests {
|
||||||
assert!(weak.inner.upgrade().is_none());
|
assert!(weak.inner.upgrade().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
fn create_temp_store() -> (Store, tempfile::TempDir) {
|
fn create_temp_store() -> (Store, tempfile::TempDir) {
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
|
|
||||||
|
|
@ -616,7 +617,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(nix_at_least = "2.33")]
|
#[cfg(nix_at_least = "2.33.0pre")]
|
||||||
fn derivation_from_invalid_json() {
|
fn derivation_from_invalid_json() {
|
||||||
let (mut store, temp_dir) = create_temp_store();
|
let (mut store, temp_dir) = create_temp_store();
|
||||||
let result = store.derivation_from_json("not valid json");
|
let result = store.derivation_from_json("not valid json");
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ pub mod context;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod string_return;
|
pub mod string_return;
|
||||||
|
pub mod nix_version;
|
||||||
|
|
|
||||||
101
nix-bindings-util/src/nix_version.rs
Normal file
101
nix-bindings-util/src/nix_version.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
//! Nix version parsing and conditional compilation support.
|
||||||
|
|
||||||
|
/// Emit [`cargo:rustc-cfg`] directives for Nix version-based conditional compilation.
|
||||||
|
///
|
||||||
|
/// Call from build.rs with the Nix version and desired version gates.
|
||||||
|
///
|
||||||
|
/// [`cargo:rustc-cfg`]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-cfg
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use nix_bindings_util::nix_version::emit_version_cfg;
|
||||||
|
/// # // Stub pkg_config so that we can render a full usage example
|
||||||
|
/// # mod pkg_config { pub fn probe_library(_: &str) -> Result<Library, ()> { Ok(Library { version: "2.33.0pre".into() }) }
|
||||||
|
/// # pub struct Library { pub version: String } }
|
||||||
|
///
|
||||||
|
/// let nix_version = pkg_config::probe_library("nix-store-c").unwrap().version;
|
||||||
|
/// emit_version_cfg(&nix_version, &["2.26", "2.33.0pre", "2.33"]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Emits `nix_at_least="2.26"` and `nix_at_least="2.33.0pre"` for version 2.33.0pre,
|
||||||
|
/// usable as `#[cfg(nix_at_least = "2.26")]`.
|
||||||
|
pub fn emit_version_cfg(nix_version: &str, relevant_versions: &[&str]) {
|
||||||
|
// Declare the known versions for cargo check-cfg
|
||||||
|
let versions = relevant_versions
|
||||||
|
.iter()
|
||||||
|
.map(|v| format!("\"{}\"", v))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-check-cfg=cfg(nix_at_least,values({}))",
|
||||||
|
versions
|
||||||
|
);
|
||||||
|
|
||||||
|
let nix_version = parse_version(nix_version);
|
||||||
|
|
||||||
|
for version_str in relevant_versions {
|
||||||
|
let version = parse_version(version_str);
|
||||||
|
if nix_version >= version {
|
||||||
|
println!("cargo:rustc-cfg=nix_at_least=\"{}\"", version_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a Nix version string into a comparable tuple `(major, minor, patch)`.
|
||||||
|
///
|
||||||
|
/// Pre-release versions (containing `"pre"`) get patch = -1, sorting before stable releases.
|
||||||
|
/// Omitted patch defaults to 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use nix_bindings_util::nix_version::parse_version;
|
||||||
|
///
|
||||||
|
/// assert_eq!(parse_version("2.26"), (2, 26, 0));
|
||||||
|
/// assert_eq!(parse_version("2.33.0pre"), (2, 33, -1));
|
||||||
|
/// assert_eq!(parse_version("2.33"), (2, 33, 0));
|
||||||
|
/// assert_eq!(parse_version("2.33.1"), (2, 33, 1));
|
||||||
|
///
|
||||||
|
/// // Pre-release versions sort before stable
|
||||||
|
/// assert!(parse_version("2.33.0pre") < parse_version("2.33"));
|
||||||
|
/// ```
|
||||||
|
pub fn parse_version(version_str: &str) -> (u32, u32, i32) {
|
||||||
|
let parts = version_str.split('.').collect::<Vec<&str>>();
|
||||||
|
let major = parts[0].parse::<u32>().unwrap();
|
||||||
|
let minor = parts[1].parse::<u32>().unwrap();
|
||||||
|
let patch = if parts.get(2).map_or(false, |s| s.contains("pre")) {
|
||||||
|
-1i32
|
||||||
|
} else {
|
||||||
|
parts
|
||||||
|
.get(2)
|
||||||
|
.and_then(|s| s.parse::<i32>().ok())
|
||||||
|
.unwrap_or(0)
|
||||||
|
};
|
||||||
|
(major, minor, patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_version() {
|
||||||
|
assert_eq!(parse_version("2.26"), (2, 26, 0));
|
||||||
|
assert_eq!(parse_version("2.33.0pre"), (2, 33, -1));
|
||||||
|
assert_eq!(parse_version("2.33"), (2, 33, 0));
|
||||||
|
assert_eq!(parse_version("2.33.1"), (2, 33, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version_ordering() {
|
||||||
|
// Pre-release versions should sort before stable
|
||||||
|
assert!(parse_version("2.33.0pre") < parse_version("2.33"));
|
||||||
|
assert!(parse_version("2.33.0pre") < parse_version("2.33.0"));
|
||||||
|
|
||||||
|
// Normal version ordering
|
||||||
|
assert!(parse_version("2.26") < parse_version("2.33"));
|
||||||
|
assert!(parse_version("2.33") < parse_version("2.33.1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue