Add automatic C library input propagation workaround
Automatically adds Nix C library build inputs based on which nix-bindings crates are dependencies, working around missing native input propagation in nix-cargo-integration. The workaround inspects the dreamLock to detect: - If the crate being built is a nix-bindings crate (adds its own inputs) - Direct dependencies on nix-bindings crates (adds their inputs) The mapping is recursive via lazyAttrsOf, so depending on nix-bindings-flake automatically brings in transitive C library dependencies. Downstream consumers can extend the mapping for their own multi-crate workspaces where crate A depends on crate B which depends on nix-bindings.
This commit is contained in:
parent
dbb00333b1
commit
6110414520
3 changed files with 156 additions and 66 deletions
25
flake.nix
25
flake.nix
|
|
@ -28,6 +28,7 @@
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
_file = ./flake.nix;
|
_file = ./flake.nix;
|
||||||
|
imports = [ ./input-propagation-workaround.nix ];
|
||||||
options.perSystem = flake-parts-lib.mkPerSystemOption (
|
options.perSystem = flake-parts-lib.mkPerSystemOption (
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
|
|
@ -46,24 +47,20 @@
|
||||||
A module to load into your nix-cargo-integration
|
A module to load into your nix-cargo-integration
|
||||||
[`perSystem.nci.projects.<name>.depsDrvConfig`](https://flake.parts/options/nix-cargo-integration.html#opt-perSystem.nci.projects._name_.depsDrvConfig) or similar such options.
|
[`perSystem.nci.projects.<name>.depsDrvConfig`](https://flake.parts/options/nix-cargo-integration.html#opt-perSystem.nci.projects._name_.depsDrvConfig) or similar such options.
|
||||||
|
|
||||||
This provides common build configuration (pkg-config, libclang, etc.) but you must
|
This provides common build configuration (pkg-config, libclang, etc.) and
|
||||||
add the specific Nix C libraries your crates need to `buildInputs`:
|
automatically adds Nix C library build inputs based on which nix-bindings
|
||||||
- `nix-bindings-util-sys` needs `nix-util-c`
|
crates are *direct* dependencies of your crate.
|
||||||
- `nix-bindings-store-sys` needs `nix-store-c`
|
|
||||||
- `nix-bindings-expr-sys` needs `nix-expr-c`
|
To disable automatic build input detection:
|
||||||
- `nix-bindings-fetchers-sys` needs `nix-fetchers-c` (Nix >= 2.29)
|
```nix
|
||||||
- `nix-bindings-flake-sys` needs `nix-flake-c`
|
nix-bindings-rust.inputPropagationWorkaround.enable = false;
|
||||||
- `nix-bindings-bdwgc-sys` needs `boehmgc`
|
```
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```nix
|
```nix
|
||||||
perSystem = perSystem@{ config, pkgs, ... }: {
|
perSystem = perSystem@{ config, ... }: {
|
||||||
nci.projects."my_project".depsDrvConfig = {
|
nci.projects."my_project".drvConfig = {
|
||||||
imports = [ perSystem.config.nix-bindings-rust.nciBuildConfig ];
|
imports = [ perSystem.config.nix-bindings-rust.nciBuildConfig ];
|
||||||
mkDerivation.buildInputs = [
|
|
||||||
perSystem.config.nix-bindings-rust.nixPackage.libs.nix-store-c
|
|
||||||
# ... add other libs as needed
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
143
input-propagation-workaround.nix
Normal file
143
input-propagation-workaround.nix
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
# Workaround for missing native input propagation in nix-cargo-integration
|
||||||
|
#
|
||||||
|
# Automatically adds Nix C library build inputs based on which nix-bindings
|
||||||
|
# crates are direct dependencies of the crate being built. The mapping is
|
||||||
|
# recursive, so depending on nix-bindings-flake will also bring in the
|
||||||
|
# transitive C library dependencies (nix-fetchers-c, nix-expr-c, etc.).
|
||||||
|
#
|
||||||
|
# Note: For multi-crate workspaces, if your crate A depends on your crate B
|
||||||
|
# which depends on nix-bindings, you'll need to add an A -> B mapping to
|
||||||
|
# `crateInputMapping` so that A also gets B's nix-bindings inputs.
|
||||||
|
{
|
||||||
|
perSystem =
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.nix-bindings-rust.inputPropagationWorkaround;
|
||||||
|
nixPackage = config.nix-bindings-rust.nixPackage;
|
||||||
|
|
||||||
|
nixLibs =
|
||||||
|
if nixPackage ? libs then
|
||||||
|
nixPackage.libs
|
||||||
|
else
|
||||||
|
# Fallback for older Nix versions without split libs
|
||||||
|
{
|
||||||
|
nix-util-c = nixPackage;
|
||||||
|
nix-store-c = nixPackage;
|
||||||
|
nix-expr-c = nixPackage;
|
||||||
|
nix-fetchers-c = nixPackage;
|
||||||
|
nix-flake-c = nixPackage;
|
||||||
|
};
|
||||||
|
|
||||||
|
# A module for nciBuildConfig that sets buildInputs based on nix-bindings dependencies.
|
||||||
|
# Uses options inspection to detect drvConfig vs depsDrvConfig context.
|
||||||
|
workaroundModule =
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# rust-cargo-lock exists in drvConfig but not depsDrvConfig
|
||||||
|
isDrvConfig = options ? rust-cargo-lock;
|
||||||
|
|
||||||
|
dreamLock = config.rust-cargo-lock.dreamLock;
|
||||||
|
depsList = dreamLock.dependencies.${config.name}.${config.version} or [ ];
|
||||||
|
|
||||||
|
# Convert list of deps to attrset keyed by name for efficient lookup
|
||||||
|
deps = builtins.listToAttrs (
|
||||||
|
map (dep: {
|
||||||
|
name = dep.name;
|
||||||
|
value = dep;
|
||||||
|
}) depsList
|
||||||
|
);
|
||||||
|
|
||||||
|
# Inputs for the crate itself if it's in the mapping
|
||||||
|
selfInputs = cfg.crateInputMapping.${config.name} or [ ];
|
||||||
|
|
||||||
|
# Inputs for direct dependencies that have mappings
|
||||||
|
depInputs = lib.concatLists (lib.attrValues (lib.intersectAttrs deps cfg.crateInputMapping));
|
||||||
|
|
||||||
|
allInputs = selfInputs ++ depInputs;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.optionalAttrs isDrvConfig {
|
||||||
|
mkDerivation.buildInputs = allInputs;
|
||||||
|
rust-crane.depsDrv.mkDerivation.buildInputs = allInputs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.nix-bindings-rust.inputPropagationWorkaround = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to automatically add Nix C library build inputs based on
|
||||||
|
which nix-bindings crates are direct dependencies.
|
||||||
|
|
||||||
|
Set to `false` to disable automatic detection and specify buildInputs manually.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
crateInputMapping = lib.mkOption {
|
||||||
|
type = lib.types.lazyAttrsOf (lib.types.listOf lib.types.package);
|
||||||
|
description = ''
|
||||||
|
Mapping from crate names to build inputs. Entries can reference
|
||||||
|
other entries for transitive dependencies.
|
||||||
|
|
||||||
|
The input propagation workaround can see direct dependencies, so
|
||||||
|
if you have `my-crate -> nix-bindings`, that works out of the box.
|
||||||
|
If you have `my-other-crate -> my-crate -> nix-bindings`, then you
|
||||||
|
need to specify `my-other-crate -> my-crate` as follows:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
nix-bindings-rust.inputPropagationWorkaround.crateInputMapping."my-other-crate" =
|
||||||
|
config.nix-bindings-rust.inputPropagationWorkaround.crateInputMapping."my-crate";
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
nix-bindings-rust.inputPropagationWorkaround.crateInputMapping = {
|
||||||
|
# -sys crates with their transitive dependencies
|
||||||
|
"nix-bindings-bdwgc-sys" = [ pkgs.boehmgc ];
|
||||||
|
"nix-bindings-util-sys" = [ nixLibs.nix-util-c.dev ];
|
||||||
|
"nix-bindings-store-sys" = [
|
||||||
|
nixLibs.nix-store-c.dev
|
||||||
|
]
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-util-sys";
|
||||||
|
"nix-bindings-expr-sys" = [
|
||||||
|
nixLibs.nix-expr-c.dev
|
||||||
|
]
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-store-sys"
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-bdwgc-sys";
|
||||||
|
"nix-bindings-fetchers-sys" = [
|
||||||
|
nixLibs.nix-fetchers-c.dev
|
||||||
|
]
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-expr-sys";
|
||||||
|
"nix-bindings-flake-sys" = [
|
||||||
|
nixLibs.nix-flake-c.dev
|
||||||
|
]
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-fetchers-sys"
|
||||||
|
++ cfg.crateInputMapping."nix-bindings-bdwgc-sys";
|
||||||
|
# High-level crates reference their -sys counterparts
|
||||||
|
"nix-bindings-bdwgc" = cfg.crateInputMapping."nix-bindings-bdwgc-sys";
|
||||||
|
"nix-bindings-util" = cfg.crateInputMapping."nix-bindings-util-sys";
|
||||||
|
"nix-bindings-store" = cfg.crateInputMapping."nix-bindings-store-sys";
|
||||||
|
"nix-bindings-expr" = cfg.crateInputMapping."nix-bindings-expr-sys";
|
||||||
|
"nix-bindings-fetchers" = cfg.crateInputMapping."nix-bindings-fetchers-sys";
|
||||||
|
"nix-bindings-flake" = cfg.crateInputMapping."nix-bindings-flake-sys";
|
||||||
|
};
|
||||||
|
|
||||||
|
nix-bindings-rust.nciBuildConfig.imports = [ workaroundModule ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
54
nci.nix
54
nci.nix
|
|
@ -1,24 +1,8 @@
|
||||||
{
|
{
|
||||||
perSystem =
|
perSystem =
|
||||||
{
|
{ config, ... }:
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
cfg = config.nix-bindings-rust;
|
cfg = config.nix-bindings-rust;
|
||||||
nixLibs =
|
|
||||||
if cfg.nixPackage ? libs then
|
|
||||||
cfg.nixPackage.libs
|
|
||||||
else
|
|
||||||
# Fallback for older Nix versions without split libs
|
|
||||||
{
|
|
||||||
nix-util-c = cfg.nixPackage;
|
|
||||||
nix-store-c = cfg.nixPackage;
|
|
||||||
nix-expr-c = cfg.nixPackage;
|
|
||||||
nix-fetchers-c = cfg.nixPackage;
|
|
||||||
nix-flake-c = cfg.nixPackage;
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# https://flake.parts/options/nix-cargo-integration
|
# https://flake.parts/options/nix-cargo-integration
|
||||||
|
|
@ -31,7 +15,7 @@
|
||||||
drvConfig = {
|
drvConfig = {
|
||||||
imports = [
|
imports = [
|
||||||
# Downstream projects import this into depsDrvConfig instead
|
# Downstream projects import this into depsDrvConfig instead
|
||||||
config.nix-bindings-rust.nciBuildConfig
|
cfg.nciBuildConfig
|
||||||
];
|
];
|
||||||
# Extra settings for running the tests
|
# Extra settings for running the tests
|
||||||
mkDerivation = {
|
mkDerivation = {
|
||||||
|
|
@ -65,39 +49,5 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Per-crate configuration: only provide the specific Nix libs each crate needs
|
|
||||||
# FIXME should use propagatedBuildInputs
|
|
||||||
nci.crates.nix-bindings-bdwgc-sys.drvConfig.mkDerivation.buildInputs = [
|
|
||||||
pkgs.boehmgc
|
|
||||||
];
|
|
||||||
nci.crates.nix-bindings-util-sys.drvConfig.mkDerivation.buildInputs = [
|
|
||||||
nixLibs.nix-util-c
|
|
||||||
];
|
|
||||||
nci.crates.nix-bindings-util.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-util-sys.drvConfig.mkDerivation.buildInputs;
|
|
||||||
nci.crates.nix-bindings-store-sys.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-util-sys.drvConfig.mkDerivation.buildInputs
|
|
||||||
++ [ nixLibs.nix-store-c ];
|
|
||||||
nci.crates.nix-bindings-store.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-store-sys.drvConfig.mkDerivation.buildInputs;
|
|
||||||
nci.crates.nix-bindings-expr-sys.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-store-sys.drvConfig.mkDerivation.buildInputs
|
|
||||||
++ [
|
|
||||||
nixLibs.nix-expr-c
|
|
||||||
pkgs.boehmgc
|
|
||||||
];
|
|
||||||
nci.crates.nix-bindings-expr.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-expr-sys.drvConfig.mkDerivation.buildInputs;
|
|
||||||
nci.crates.nix-bindings-fetchers-sys.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-expr-sys.drvConfig.mkDerivation.buildInputs
|
|
||||||
++ [ nixLibs.nix-fetchers-c ];
|
|
||||||
nci.crates.nix-bindings-fetchers.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-fetchers-sys.drvConfig.mkDerivation.buildInputs;
|
|
||||||
nci.crates.nix-bindings-flake-sys.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-fetchers-sys.drvConfig.mkDerivation.buildInputs
|
|
||||||
++ [ nixLibs.nix-flake-c ];
|
|
||||||
nci.crates.nix-bindings-flake.drvConfig.mkDerivation.buildInputs =
|
|
||||||
config.nci.crates.nix-bindings-flake-sys.drvConfig.mkDerivation.buildInputs;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue