Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override compile flags for a single package in nixos?

How can I override compile flags (as in CFLAGS) for a single package in NixOS/Nix environments?

Here's what I've got by now:

let
   optimizeForThisHost = pkg:
     pkgs.lib.overrideDerivation pkg (old: {
       exportOptimizations = ''
         export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -fPIC -O3 -march=native"
       '';
       phaseNames = ["exportOptimizations"] ++ old.phaseNames;
     });
in
muttWithoutThings = pkgs: (pkgs.mutt.override {
    sslSupport  = false;
    saslSupport = false;
    imapSupport = false;
    withSidebar = false;
 };
});

mutt = pkgs:
    (optimizeForThisHost (muttWithoutThings pkgs));

in my configuration.nix, though this fails with

error: attribute ‘phaseNames’ missing
like image 501
musicmatze Avatar asked Feb 09 '17 12:02

musicmatze


2 Answers

Here is a working example that builds (and runs) a copy of GNU hello with custom compiler flags:

nix-shell -p 'hello.overrideDerivation (old: { NIX_CFLAGS_COMPILE = "-Ofoo"; })' --run "hello --version"

If you want to convince yourself whether this really works, try passing a non-existent flag to the compiler, like -Ofoo, and verify that the builds fails as expected.

More information about the overrideDerivation function (and similar alternatives) can found in the Nixpkgs manual at http://nixos.org/nixpkgs/manual/index.html#sec-pkg-overrideDerivation.

like image 133
Peter Simons Avatar answered Sep 22 '22 16:09

Peter Simons


I managed to write a function which I can apply to the packages I want to compile with custom flags:

  optimizeWithFlags = pkg: flags:
    pkgs.lib.overrideDerivation pkg (old:
    let
      newflags = pkgs.lib.foldl' (acc: x: "${acc} ${x}") "" flags;
      oldflags = if (pkgs.lib.hasAttr "NIX_CFLAGS_COMPILE" old)
        then "${old.NIX_CFLAGS_COMPILE}"
        else "";
    in
    {
      NIX_CFLAGS_COMPILE = "${oldflags} ${newflags}";
    });

This function takes a package and a list of strings (which are the flags) and builds a new package with the existing one, but with the additional compiler flags.

For convenience, I wrote another set of helper functions:

  optimizeForThisHost = pkg:
    optimizeWithFlags pkg [ "-O3" "-march=native" "-fPIC" ];

  withDebuggingCompiled = pkg:
    optimizeWithFlags pkg [ "-DDEBUG" ];

Now, I can override packages (here mutt and dmenu):

  muttWithoutThings = pkgs: (pkgs.mutt.override {
    sslSupport  = false;
    saslSupport = false;
    imapSupport = false;
    withSidebar = false;
  });

  mutt = pkgs:
    (utils pkgs).withoutConfigureFlag "--enable-debug"
    ((utils pkgs).optimizeForThisHost (muttWithoutThings pkgs)
    );

  dmenu = pkgs:
    (utils pkgs).optimizeForThisHost
    (pkgs.dmenu.override {
      patches = [ ./patches/dmenu-fuzzymatch-4.6.diff ];
    });

In the above utils is utils = pkgs: import ./util.nix { pkgs = pkgs; }; and the util.nix file returns a function which spits out a set of functions.

like image 38
musicmatze Avatar answered Sep 22 '22 16:09

musicmatze