NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.37k stars 14.33k forks source link

Package request: Picamera2 #230426

Open zefrof opened 1 year ago

zefrof commented 1 year ago

Project description

Python library for managing raspberry pi camera.

Metadata

Faeranne commented 7 months ago

I've successfully gotten picamera2 to build under nix, but several issues make it unlikely to be acceptable for nixpkgs any time soon.

First, libcamera must be rebuilt with rpi support enabled. for whatever reason, building aarch64-linux packages still doesn't enable rpi support, and my guess is libcamera is doing some detection that nix breaks.

Second, raspberry pi has patched libcamera to build the actual python bindings, which is a clunky but necessary fix.

Third, as mentioned in #236443, python-prctl needs a small change to get it compiling again.

And finally, the biggest issue is that compiling simplejpeg as is will likely be an uphill battle. simplejpeg's build tool directly fetches multiple git repos mid-build, and would need to be patched quite a bit to remove that impurity. Fortunatly it is exclusively used for the jpeg renderer, which is only used if you save jpeg images directly from picamera2. Using any other renderer or numpy arrays bypasses it all together.

I have not tested beyond successful build and import, and I know py-kms++ still needs to be packaged too before most of picamera2 is ready to be packaged.

If someone else watching this needs a starting point for building proper nixpkgs, and wants to take on the burden, be my guest. Otherwise, I'll likely get to this in a few months, assuming I can get all the pieces together.

bohendo commented 2 months ago

Care to share what you have so far @Faeranne? I've already done some tinkering and am willing to do more to get picamera2 on nixos. Here's my (broken) attempt at a picamera2.nix:

{ config, lib, pkgs, modulesPath, ... }: with lib;
let
  pyVersion = "python311";
  python = pkgs.${pyVersion};
  pyPkgs = pkgs.${pyVersion + "Packages"};
  skipTests = { doCheck = false; checkPhase = "true"; checkInputs = []; };

  # compiles fine (I think) but tests are broken
  python-prctl = pyPkgs.python-prctl.overridePythonAttrs (old: skipTests);

  libcamera-py = pkgs.libcamera.overrideAttrs (oldAttrs: {
    mesonFlags = (oldAttrs.mesonFlags or []) ++ [ "-Dpycamera=enabled" ];
    postPatch = ''
      patchShebangs src/py/ utils/
    '';
    buildInputs = (oldAttrs.buildInputs or []) ++ [
      python pyPkgs.pybind11
    ];
    nativeBuildInputs = (oldAttrs.nativeBuildInputs or []) ++ [
      pyPkgs.pip pyPkgs.setuptools pkgs.makeWrapper
    ];
    preBuild = (oldAttrs.preBuild or "") + ''
      export MESON_BUILD_ROOT=$PWD
      export PATH="${python}/bin:$PATH"
    '';
  });

  v4l2-python3 = pyPkgs.buildPythonPackage rec {
    pname = "v4l2-python3";
    version = "0.3.5";
    format = "setuptools";
    doCheck = false;
    src = pyPkgs.fetchPypi {
      inherit pname version;
      sha256 = "sha256-5+JHOcGBbWSoKSm4F4GtpOVkCXQVejlYWtLgLf2xAv0=";
    };
    buildInputs = with pkgs; [ libv4l v4l-utils ];
  };

  # Broken :(
  simplejpeg = pyPkgs.buildPythonPackage rec {
    pname = "simplejpeg";
    version = "1.7.6";
    format = "pyproject";
    doCheck = false;
    src = pyPkgs.fetchPypi {
      inherit pname version;
      sha256 = "sha256-iepHhOqgnt0RsMre2cQDJsSHK6kjL/FwXVtzJJLnrKg=";
    };
    buildInputs = [ pkgs.libjpeg ];
    nativeBuildInputs = [
      pkgs.cmake pkgs.gnumake pyPkgs.cmake
      pyPkgs.cython pyPkgs.wheel pyPkgs.setuptools
    ];
    propagatedBuildInputs = [ pyPkgs.numpy ];
  };

  PiDNG = pyPkgs.buildPythonPackage rec {
    pname = "pidng";
    version = "4.0.9";
    format = "setuptools";
    doCheck = false;
    src = pyPkgs.fetchPypi {
      inherit pname version;
      sha256 = "sha256-Vg6wCAhvinFf2eGrmYgXp9TIUAp/Fhuc5q9asnUB+Cw=";
    };
  };

  picamera2 = pyPkgs.buildPythonPackage rec {
    pname = "picamera2";
    version = "0.3.18";
    format = "setuptools";
    doCheck = false;
    src = pyPkgs.fetchPypi {
      inherit pname version;
      sha256 = "sha256-WONtPlLO0MiBSxrLH93pW87CHKtkqJ7/SlsOQF+CIP0=";
    };
    propagatedBuildInputs = [
      # from nixpkgs
      pyPkgs.setuptools pyPkgs.av pyPkgs.piexif pyPkgs.numpy pyPkgs.pillow
      # custom
      PiDNG python-prctl simplejpeg
      # bindings
      libcamera-py v4l2-python3 (pyPkgs.toPythonModule libcamera-py)
    ];
  };
in
  (python.withPackages (ps: with ps; [
    matplotlib numpy pillow pyopengl v4l2-python3 pyqt5 setuptools
    libcamera-py (toPythonModule libcamera-py) picamera2
  ]))
Faeranne commented 2 months ago

Yeah! Everything I've done to get it working is in Faeranne/rpi-camera-py-nix. Let me know if you need anything else, and I can make it happen. :+1: