1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

packaging-nix: improve packaging + cross-compilation

- Adds and documents some simple cross-compiling support.
- More documentation in the `flake.nix`.
- Add nixpkgs overlay (though undocumented).

Signed-off-by: Philipp Jungkamp <Philipp.Jungkamp@opal-rt.com>
This commit is contained in:
Philipp Jungkamp 2023-06-08 17:14:31 +02:00
parent c5606d7ac9
commit 03ad3a77aa
4 changed files with 214 additions and 82 deletions

View file

@ -56,10 +56,23 @@ You can also install `villas` into your local profile and have it available in
nix profile install 'github:VILLASframework/node?dir=packaging/nix#villas'
```
If you don't want to add it directly into the global path you could add it into
the flake registry as well.
```shell
nix registy add 'github:VILLASframework/node?dir=packaging/nix#villas'
```
This allows you to substitue all references to
`github:VILLASframework/node?dir=packaging/nix#villas` with a simple `villas`.
I'll be using the `villas` registry entry in the following sections.
## Development
You can easily setup a development shell environment for `villas` by using the
`devShells` provided in the [`flake.nix`] using `nix develop`.
Try for example these commands in the repository root to create a new shell with
all required dependecies to build various configurations of `villas`.
```shell
# create a shell with all required build dependecies but without most optional ones
@ -87,6 +100,7 @@ images without worrying about missing dependencies or Copying things inbetween
nothing else can be done using only a few lines of Nix.
Here we build a docker image containing the `#villas` flake output:
```shell
# `docker load` reads OCI images from stdin
# `nix build --impure --expr` builds a derivation from an impure Nix expression
@ -94,8 +108,7 @@ Here we build a docker image containing the `#villas` flake output:
# `--print-out-paths` prints the built image's path to stdout
docker load < $(nix build --no-link --print-out-paths --impure --expr '
let
ref = "github:VILLASframework/node?dir=packaging/nix";
villas = (builtins.getFlake ref).packages.x86_64-linux.villas;
villas = (builtins.getFlake "villas").packages.x86_64-linux.villas;
pkgs = (builtins.getFlake "nixpkgs").legacyPackages.x86_64-linux;
in
pkgs.dockerTools.buildImage {
@ -110,6 +123,40 @@ docker load < $(nix build --no-link --print-out-paths --impure --expr '
See https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-dockerTools
## Simple cross-compilation to aarch64
The flake currently supports `x86_64-linux` and `aarch64-linux` systems. But
especially on some weaker `aarch64` target machines, compiling `villas` from
source is rather cumbersome. This flake has a non-standard `crossPackages`
flake output. This is currently only useful for cross-compiling from `x86_64`
to `aarch64`.
```shell
nix build villas#crossPackages.x86_64-linux.aarch64-multiplatform.villas
```
If your target has a nix installation you can directly build and copy the
cross-compiled package using `nix copy`.
```shell
# build and copy in one
nix copy villas#crossPackages.x86_64-linux.aarch64-multiplatform.villas --to ssh-ng://target-system
```
```shell
# build the cross-compiled package
nix build villas#crossPackages.x86_64-linux.aarch64-multiplatform.villas
# copy it over
nix copy $(readlink result) --to ssh-ng://target
# add the cross-compiled package to the target's PATH
ssh target nix profile add $(readlink result)
```
Further parameters for port or user of the ssh connection can only be specified
in the ssh configuration files.
## Customization
The [`villas.nix`] file contains the Nix "derivation" used to
@ -134,11 +181,10 @@ See https://nixos.org/manual/nixpkgs/stable/#chap-overrides
# `pkgs` is the set of `x86_64-linux` packages provided by the flake
nix build --impure --expr '
let
ref = "github:VILLASframework/node?dir=packaging/nix";
pkgs = (builtins.getFlake ref).packages.x86_64-linux;
pkgs = (builtins.getFlake "villas").packages.x86_64-linux;
in
pkgs.villas-minimal.override {
withConfig = true;
withExtraConfig = true;
withNodeIec60870 = true;
}
'
@ -180,7 +226,8 @@ Here is a basic flake to build upon:
packages.x86_64-linux = rec {
default = villas-custom;
villas-custom = villas-pkgs.villas-minimal.override {
withConfig = true;
version = "custom";
withExtraConfig = true;
withNodeIec60870 = true;
};
};
@ -228,7 +275,8 @@ typical Nix usage. A more interesting use of Nix would be a custom Nix shell
environment containing your `villas-custom` and other tools of your choice.
Here is a more complete `flake.nix` containing `devShells` available to
`nix develop` and an OCI image:
`nix develop` and an OCI image.
```nix
# flake.nix
{

View file

@ -16,6 +16,24 @@
"type": "github"
}
},
"fpga": {
"flake": false,
"locked": {
"lastModified": 1679417867,
"narHash": "sha256-HHIsOnuQOq0Ytd22VMSHpTbecHpcheF1xLkslqxXOsk=",
"ref": "refs/heads/master",
"rev": "29f81016b2317667a2b21fbcf74ea66986a84c03",
"revCount": 530,
"submodules": true,
"type": "git",
"url": "https://github.com/VILLASframework/fpga.git"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://github.com/VILLASframework/fpga.git"
}
},
"lib60870": {
"flake": false,
"locked": {
@ -68,6 +86,7 @@
"root": {
"inputs": {
"common": "common",
"fpga": "fpga",
"lib60870": "lib60870",
"libiec61850": "libiec61850",
"nixpkgs": "nixpkgs"

View file

@ -5,7 +5,12 @@
nixpkgs.url = "github:NixOS/nixpkgs";
common = {
url = "github:VILLASframework/common?submodules=1";
url = "github:VILLASframework/common";
flake = false;
};
fpga = {
url = "git+https://github.com/VILLASframework/fpga.git?submodules=1";
flake = false;
};
@ -26,46 +31,80 @@
...
} @ inputs: let
inherit (nixpkgs) lib;
# supported systems for native compilation
supportedSystems = ["x86_64-linux" "aarch64-linux"];
# supported systems to cross compile to
supportedCrossSystems = ["aarch64-multiplatform"];
# generate attributes corresponding to all the supported systems
forSupportedSystems = lib.genAttrs supportedSystems;
legacyPackages = forSupportedSystems (
system:
import nixpkgs {
inherit system;
overlays = [(final: prev: self.packages.${system})];
}
);
# generate attributes corresponding to all supported combinations of system and crossSystem
forSupportedCrossSystems = f: forSupportedSystems (system: lib.genAttrs supportedCrossSystems (f system));
# this overlay can be applied to nixpkgs (see `pkgsFor` below for an example)
overlay = final: prev: packagesWith final;
# initialize nixpkgs for the specified `system`
pkgsFor = system:
import nixpkgs {
inherit system;
overlays = [overlay];
};
# initialize nixpkgs for cross-compiling from `system` to `crossSystem`
crossPkgsFor = system: crossSystem: (pkgsFor system).pkgsCross.${crossSystem};
# build villas and its dependencies for the specified `pkgs`
packagesWith = pkgs: rec {
default = villas;
villas-minimal = pkgs.callPackage ./villas.nix {
src = ../..;
version = "minimal";
inherit (inputs) fpga common;
};
villas = villas-minimal.override {
version = "full";
withAllExtras = true;
withAllFormats = true;
withAllHooks = true;
withAllNodes = true;
};
lib60870 = pkgs.callPackage ./lib60870.nix {
src = inputs.lib60870;
};
libiec61850 = pkgs.callPackage ./libiec61850.nix {
src = inputs.libiec61850;
};
};
in {
formatter = forSupportedSystems (system: legacyPackages.${system}.alejandra);
# standard flake attribute for normal packages (not cross-compiled)
packages = forSupportedSystems (
system: let
pkgs = legacyPackages.${system};
in rec {
default = villas;
villas-minimal = pkgs.callPackage ./villas.nix {
src = ../..;
common = inputs.common;
};
villas = villas-minimal.override {
withConfig = true;
withProtobuf = true;
withAllNodes = true;
};
lib60870 = pkgs.callPackage ./lib60870.nix {
src = inputs.lib60870;
};
libiec61850 = pkgs.callPackage ./libiec61850.nix {
src = inputs.libiec61850;
};
}
system:
packagesWith (pkgsFor system)
);
# non-standard attribute for cross-compilated packages
crossPackages = forSupportedCrossSystems (
system: crossSystem:
packagesWith (crossPkgsFor system crossSystem)
);
# standard flake attribute allowing you to add the villas packages to your nixpkgs
overlays = {
default = overlay;
};
# standard flake attribute for defining developer environments
devShells = forSupportedSystems (
system: let
pkgs = legacyPackages.${system};
pkgs = pkgsFor system;
shellHook = ''
[ -z "$PS1" ] || exec $SHELL
'';
@ -85,9 +124,11 @@
};
}
);
# standard flake attribute to add additional checks to `nix flake check`
checks = forSupportedSystems (
system: let
pkgs = legacyPackages.${system};
pkgs = pkgsFor system;
in {
fmt = pkgs.runCommand "check-fmt" {} ''
cd ${self}
@ -95,5 +136,8 @@
'';
}
);
# standard flake attribute specifying the formatter invoked on `nix fmt`
formatter = forSupportedSystems (system: (pkgsFor system).alejandra);
};
}

View file

@ -1,72 +1,87 @@
{
# build dependencies
cmake,
common,
lib,
makeWrapper,
pkg-config,
stdenv,
# general configuration
src,
# configuration
withConfig ? false,
withProtobuf ? false,
version,
withAllExtras ? false,
withAllFormats ? false,
withAllHooks ? false,
withAllNodes ? false,
withExtraConfig ? withAllExtras,
withExtraGraphviz ? false, # unknown type boolean in villas-graph
withFormatProtobuf ? withAllFormats,
withHookLua ? false, # deprecated functions
withNodeAmqp ? false, # deprecated functions
withNodeComedi ? withAllNodes,
withNodeFpga ? false, # spdlog formatting error
withNodeIec60870 ? withAllNodes,
withNodeIec61850 ? withAllNodes,
withNodeInfiniband ? withAllNodes,
withNodeKafka ? withAllNodes,
withNodeMqtt ? withAllNodes,
withNodeRedis ? withAllNodes,
withNodeNanomsg ? withAllNodes,
withNodeRedis ? false, # spdlog formatting error
withNodeRtp ? withAllNodes,
withNodeSocket ? withAllNodes,
withNodeTemper ? withAllNodes,
withNodeUldaq ? withAllNodes,
withNodeZeromq ? withAllNodes,
withNodeNanomsg ? withAllNodes,
withNodeRtp ? withAllNodes,
withNodeTemper ? withAllNodes,
withNodeSocket ? withAllNodes,
# dependencies
comedilib,
# minimal dependencies
cmake,
common,
coreutils,
fpga,
graphviz,
lib,
makeWrapper,
pkg-config,
stdenv,
# optional dependencies
comedilib,
curl,
czmq,
gnugrep,
graphviz,
jansson,
lib60870,
libconfig,
libiec61850,
libre,
libnl,
libre,
libsodium,
libuldaq,
libusb,
libuuid,
libwebsockets,
lua,
mosquitto,
nanomsg,
openssl,
protobuf,
pkgsBuildBuild,
protobufc,
protobufcBuildBuild ? pkgsBuildBuild.protobufc,
rabbitmq-c,
rdkafka,
rdma-core,
redis-plus-plus,
spdlog,
}:
stdenv.mkDerivation {
inherit src version;
pname = "villas";
version = "release";
src = src;
cmakeFlags = [
"-DWITH_FPGA=OFF"
"-DDOWNLOAD_GO=OFF"
"-DCMAKE_BUILD_TYPE=Release"
# the default -O3 causes g++ warning false positives on
# 'array-bounds' and 'stringop-overflow' for villas-relay
"-DCMAKE_CXX_FLAGS_RELEASE=-Wno-error"
];
cmakeFlags =
[
"-DDOWNLOAD_GO=OFF"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_CXX_FLAGS_RELEASE=-Wno-error=maybe-uninitialized"
]
++ lib.optionals withFormatProtobuf ["-DCMAKE_FIND_ROOT_PATH=${protobufcBuildBuild}/bin"];
preConfigure = ''
rm -d common && ln -sf ${common} common
rm -df common
rm -df fpga
ln -s ${common} common
${lib.optionalString withNodeFpga "ln -s ${fpga} fpga"}
'';
postInstall = ''
patchShebangs --build $out/bin/villas
wrapProgram $out/bin/villas \
--set PATH ${lib.makeBinPath [(placeholder "out") gnugrep coreutils]}
'';
@ -75,6 +90,7 @@ stdenv.mkDerivation {
makeWrapper
pkg-config
];
depsBuildBuild = lib.optionals withFormatProtobuf [protobufcBuildBuild];
buildInputs =
[
jansson
@ -84,21 +100,26 @@ stdenv.mkDerivation {
curl
spdlog
]
++ lib.optionals withConfig [libconfig]
++ lib.optionals withProtobuf [protobuf protobufc]
++ lib.optionals withExtraConfig [libconfig]
++ lib.optionals withExtraGraphviz [graphviz]
++ lib.optionals withFormatProtobuf [protobufc]
++ lib.optionals withHookLua [lua]
++ lib.optionals withNodeAmqp [rabbitmq-c]
++ lib.optionals withNodeComedi [comedilib]
++ lib.optionals withNodeZeromq [czmq libsodium]
++ lib.optionals withNodeIec60870 [lib60870]
++ lib.optionals withNodeIec61850 [libiec61850]
++ lib.optionals withNodeSocket [libnl]
++ lib.optionals withNodeRtp [libre]
++ lib.optionals withNodeUldaq [libuldaq]
++ lib.optionals withNodeTemper [libusb]
++ lib.optionals withNodeInfiniband [rdma-core]
++ lib.optionals withNodeKafka [rdkafka]
++ lib.optionals withNodeMqtt [mosquitto]
++ lib.optionals withNodeNanomsg [nanomsg]
++ lib.optionals withNodeKafka [rdkafka]
++ lib.optionals withNodeInfiniband [rdma-core];
++ lib.optionals withNodeRedis [redis-plus-plus]
++ lib.optionals withNodeRtp [libre]
++ lib.optionals withNodeSocket [libnl]
++ lib.optionals withNodeTemper [libusb]
++ lib.optionals withNodeUldaq [libuldaq]
++ lib.optionals withNodeZeromq [czmq libsodium];
meta = with lib; {
mainProgram = "villas";
description = "a tool connecting real-time power grid simulation equipment";
homepage = "https://villas.fein-aachen.org/";
license = licenses.asl20;