ffmpegnixnixos

Nix package: Pass build flag --extra-cflags to ffmpeg at compile time


I'm a little inexperienced with Nix and NixOS and am struggling a bit with this ffmpeg source build. Any advice is appreciated!

Goal

Build ffmpeg from source with --extra-cflags="-pipe -O3 -march=znver3 -ffat-lto-objects", ideally using a flake or overlay or similar so that I can build off the existing ffmpeg nix package and maybe even reproducible builds.

Attempts

I've been trying to follow different advice I've seen online, but looking at ffmpeg in nixpkgs, I'm not sure what I could patch or override. Since configureFlags happens inside the stdenv.mkderivation block, when I try to override it, it doesn't seem to have scope into this variable (and since the derivation explicitly sets onfigurePlatforms = [];, I'm not sure if that would clobber the override changes unless I tried to override the whole long derivation).

Looking at the ffmpeg configure script, it seemed like environment variable cflags / cxxflags won't be respected, but it will take them from the --extra-cflags argument, but I could be missing something.

Flake attempt

Here's an example flake.nix I forked from an example I saw at this github repo

{
  description = "A full build of ffmpeg, including the proprietary stuff";

  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = true;
        };

        overrides = {
          ffmpeg = pkgs.ffmpeg-full;
          # If this did work, I'm not sure how it would combine with the derivation in the existing package, e.g. if it would get overridden
          configureFlags = [ "--extra-cflags -march=znver3 -O3 -pipe -ffat-lto-objects" ];
          withHeadlessDeps = true;
          nonfreeLicensing = true;
          # more options here once things are working above
        };
      in
      rec {
        packages.ffmpeg-custom = pkgs.ffmpeg-full.override overrides;
        defaultPackage = packages.ffmpeg-custom;
      }
    );
}

when building with nix profile install, I encounter the error:

       error: function 'anonymous lambda' called with unexpected argument 'configureFlags'

       at /nix/store/d9wpzgyjlpw1424kw2lyilah6690fnk3-source/pkgs/development/libraries/ffmpeg-full/default.nix:1:1:

            1| { lib, stdenv, buildPackages, ffmpeg, addOpenGLRunpath, pkg-config, perl, texinfo, yasm
             | ^
            2| /*

presumably since configureFlags is defined in the derivation in the original package.

Overlay in configuration.nix attempt

I tried adding this to my /etc/nixos/configuration.nix also without success:

nixpkgs.overlays = [
  (self: super: {
    ffmpeg-full = super.ffmpeg-full.override {
      configureFlags = [
        "--enable-hardcoded-tables"
        "--extra-cflags -march=znver3 -O3 -pipe -ffat-lto-objects"
      ] ++ super.ffmpeg-full.configureFlags;
    };
  })
];

when building with nixos-rebuild switch I get the same error:

       error: function 'anonymous lambda' called with unexpected argument 'configureFlags'

       at /nix/store/amxbqlhq11xfrbs4vdsyi04fap0abx0v-nixos-23.11/nixos/pkgs/development/libraries/ffmpeg/generic.nix:3:1:

            2|
            3| { lib, stdenv, buildPackages, removeReferencesTo, addOpenGLRunpath, pkg-config, perl, texinfo, yasm
             | ^
            4|

Context

I have a NixOS machine that does very long-running ffmpeg encodes nearly all the time. I was hoping to rebuild headless ffmpeg with more aggressive cflags and maybe some extra options. I hope to benchmark performance differences between different builds.

I'll probably use this as an excuse to also build ffmpeg with some extra nonfree dependencies too.


Solution

  • I fixed it with help from the NixOS discourse forum here.

    Using overrideAttrs allowed me to edit values inside the mkderivation scope. After resolving that, I encountered an issue where the spaces in the --extra-cflags="-O3 -pipe ..." flag was being split into separate flags, and adding quotes would become escaped at config time. This was solved by setting it in preConfigure as illustrated below.

    # /etc/nixos/configuration.nix
    
    nixpkgs.overlays = [
      (self: super: {
        ffmpeg-headless = super.ffmpeg-headless.overrideAttrs (old: {
          preConfigure = ''
            configureFlagsArray+=(
              "--extra-cflags=-O3 -pipe -march=znver3 -ffat-lto-objects -frecord-gcc-switches"
            )
          '';
          configureFlags = old.configureFlags;
        });
      })
    ];