Add flag `--extra-cflags` to ffmpeg compilation

Hi everyone! I’m pretty inexperienced with NixOS and was struggling to make an overlay or flake to compile ffmpeg with the --extra-cflags="-some -flags" option (plus a couple other feature flags).

I was a little lost going through the nixpkgs ffmpeg config. I see the configureFlags list where I probably want to put this flag, but since it’s inside the stdenv.mkDerivation block, the override or flake doesn’t seem to have that variable in scope.

For example, if I put configureFlags in my overrides, I get an error like error: function 'anonymous lambda' called with unexpected argument 'configureFlags'. I wrote about this in more detail in this stack overflow question.

Is there a way to modify/override things in the package’s stdenv.mkDerivation scope?

Thanks!

Have you tried overrideAttrs(old: { . . . })?

https://ryantm.github.io/nixpkgs/using/overrides/#sec-pkg-overrideAttrs

1 Like

Thanks for the tip! That did get me a bit closer! :slight_smile:

If you don’t mind me asking another question in the same thread, it seems like now I’m running into an issue with double-quotes getting escaped, even when surrounded by two single quotes:

# /etc/nixos/configuration.nix

nixpkgs.overlays = [
  (self: super: {
    ffmpeg-headless = super.ffmpeg-headless.overrideAttrs (old: {                  
      configureFlags = old.configureFlags ++ [ ''--extra-cflags="-O3 -pipe -march=znver3 -ffat-lto-objects -ftree-loop-distribute-patterns"'' ];
      NIX_CFLAGS_COMPILE = "-pipe -O3 -march=znver3 -ffat-lto-objects -ftree-loop-distribute-patterns";
      withGPL = true;
      withStatic = true;
      withGrayscale = true;                                                        
      withVersion3 = true;                                                         
      withUnfree = true;                                                           
      withNvcodec = true;                                                          
      withBluray = true;                                                           
      withDvdnav = true;
      withDvdread = true;
      withDrm = true;
      withOpencl = true;
      withPulse = true;
      withSvg = true;
      withVmaf = true;
      withVulkan = true;
      withSvtav1 = true;
      withZmq = true;
    });
  })
];
];

then running nixos-rebuild switch, I encounter the following error:

[ ... ]
Running phase: configurePhase
configure flags: --disable-static --prefix=/nix/store/din2jmdfmrs36q12z68bh5wabsqn0667-ffmpeg-headless-6.0 --target_os=linux --arch=x86_64 --pkg-config=pkg-config --enable-gpl --enable-version3 --disable-nonfree --enable-shared --enable-pic --disable-small --enable-runtime-cpudetect --disable-gray --enable-swscale-alpha --enable-hardcoded-tables --enable-safe-bitstream-reader --enable-pthreads --disable-w32threads --disable-os2threads --enable-network --enable-pixelutils --datadir=/nix/store/4dl0afym7rs44d3rr83w3diqdakwvlby-ffmpeg-headless-6.0-data/share/ffmpeg --enable-ffmpeg --disable-ffplay --enable-ffprobe --bindir=/nix/store/816zkcs1nljwmpf22skw116nwi3dkpgs-ffmpeg-headless-6.0-bin/bin --enable-avcodec --enable-avdevice --enable-avfilter --enable-avformat --enable-avutil --enable-postproc --enable-swresample --enable-swscale --libdir=/nix/store/mcyv519k4bvvz8lpy71kn4kacb9msnry-ffmpeg-headless-6.0-lib/lib --incdir=/nix/store/hn6gmm93bjnlr624mx4x5ggz55glimh6-ffmpeg-headless-6.0-dev/include --enable-doc --enable-htmlpages --enable-manpages --mandir=/nix/store/6fmi7zphf3nl064qh3cvvl05ciz1dpy3-ffmpeg-headless-6.0-man/share/man --enable-podpages --enable-txtpages --docdir=/nix/store/z1jkc7dkz9100nahab5xbgn80z0z6sk0-ffmpeg-headless-6.0-doc/share/doc/ffmpeg --enable-alsa --enable-bzlib --disable-libcelt --disable-cuda --disable-cuda-llvm --enable-libdav1d --disable-libfdk-aac --disable-libflite --enable-fontconfig --enable-libfreetype --disable-frei0r --disable-libfribidi --disable-libgme --enable-gnutls --disable-libgsm --disable-ladspa --enable-libmp3lame --disable-libaom --enable-libass --disable-libbluray --disable-libbs2b --disable-libdc1394 --enable-libdrm --enable-iconv --disable-libjack --disable-libmfx --disable-libmodplug --disable-libmysofa --enable-libopus --disable-librsvg --enable-libsrt --enable-libssh --disable-libtensorflow --enable-libtheora --enable-libv4l2 --enable-v4l2-m2m --enable-vaapi --disable-vdpau --enable-libvorbis --disable-libvmaf --enable-libvpx --disable-libwebp --disable-xlib --disable-libxcb --disable-libxcb-shm --disable-libxcb-xfixes --disable-libxcb-shape --disable-libxml2 --enable-lzma --enable-cuvid --enable-nvdec --enable-nvenc --disable-openal --disable-opencl --disable-libopencore-amrnb --disable-opengl --disable-libopenh264 --disable-libopenjpeg --disable-libopenmpt --disable-libpulse --disable-librav1e --enable-libsvtav1 --disable-librtmp --disable-sdl2 --enable-libsoxr --enable-libspeex --disable-libvidstab --disable-libvo-amrwbenc --enable-libx264 --enable-libx265 --disable-libxavs --enable-libxvid --disable-libzmq --enable-libzimg --enable-zlib --disable-vulkan --disable-libglslang --disable-libsmbclient --disable-debug --enable-optimizations --disable-extra-warnings --disable-stripping --extra-cflags=\"-O3 -pipe -march=znver3 -ffat-lto-objects -ftree-loop-distribute-patterns\"
./configure: eval: line 889: unexpected EOF while looking for matching `"'
Unknown option "-pipe".
See ./configure --help for available options.
error: builder for '/nix/store/2anicrq1l76yszih2kjiqsqf3ilpmdv7-ffmpeg-headless-6.0.drv' failed with exit code 1
[ ... ]

Even if I backslash-escape the double-quotes, something along the way then escapes my escape characters. e.g. configureFlags = old.configureFlags ++ [ ''--extra-cflags=\"-O3 -pipe -march=znver3 -ffat-lto-objects -ftree-loop-distribute-patterns\"'' ]; yields an error in the configure phase that transformed it into --extra-cflags=\\\"-O3 -pipe -march=znver3 -ffat-lto-objects -ftree-loop-distribute-patterns\\\"

I thought the two single quotes would prevent escaping like that occurring, so I’m not really sure why this is happening.

You cannot currently use spaces in configureFlags and most other such arguments. The array will be turned into an environment variable by Nix by joining it with spaces:

nix-repl> lib.traceVal (builtins.toString ["foo" "bar" ''\"with space\"''])
trace: foo bar \"with space\"
"foo bar \\\"with space\\\""

Then stdenv will pass it to configure unquoted:

so the variable will be split along $IFS.

You need to use configureFlagsArray in preConfigure instead:

Or enable __structuredAttrs to be able to pass configureFlags as an actual array. But then you should remove the quotes.

Example comparing flags with __structuredAttrs and without
 $ nix-build test.nix -I nixpkgs=$PWD
this derivation will be built:
  /nix/store/vbfp311nvb5plnizra631yn25wig1a7f-foo.drv
building '/nix/store/vbfp311nvb5plnizra631yn25wig1a7f-foo.drv'...
structuredAttrs is enabled
*foo*
*bar*
*\"with space\"*
/nix/store/2ba05g7picfd7zmbxprfcs6h7waqsrwf-foo

$ nix-build test.nix -I nixpkgs=$PWD --arg structuredAttrs false
this derivation will be built:
  /nix/store/d6978vj93mrin4h94b99h7a5j0dg52h6-foo.drv
building '/nix/store/d6978vj93mrin4h94b99h7a5j0dg52h6-foo.drv'...
*foo*
*bar*
*\"with*
*space\"*
/nix/store/rms2gl2ixsvrr3infk8f3czk2q81q6xp-foo
{ structuredAttrs ? true }:

let
  pkgs = import <nixpkgs> {};
in
pkgs.runCommand "foo" {
  __structuredAttrs = structuredAttrs;
  fooFlags = [
    "foo"
    "bar"
    ''\"with space\"''
  ]; 
}
  ''
    _accumFlagsArray fooFlags
    for f in "''${flagsArray[@]}"; do
        echo "*''${f}*"
    done
    touch "$out"
  ''
1 Like

Why are you replicating the same string in NIX_CFLAGS_COMPILE and inside configureFlags?

And, since you are using a string with whitespace, you should try configureFlagsArray

https://nixos.org/manual/nixpkgs/stable/#ssec-configure-phase

This worked, thank you for the help and the examples! :slight_smile:

I think at some point I threw NIX_CFLAGS_COMPILE in there with hopes that ffmpeg would pick it up and never removed it. I can probably delete that line now. :slight_smile: