Nixpkgs: Missing documentation: Override compile flags for a package

Created on 11 Feb 2017  Â·  15Comments  Â·  Source: NixOS/nixpkgs

Issue description

I cannot find any documentation how to override compile flags for a single package.

For example, I want to build pkgs.dmenu with -O3 and -march=native.
One step further, I'd love to have a helper function I could pass packages to, which automatically overrides certain flags, E.G.:

let
  dmenu = util.optimizeWithFlags [ "-O3", "-march=native" ] pkgs.dmenu;
  mutt = util.optimizeWithFlags [ "-march=native" ] pkgs.mutt;
in
  [ mutt dmenu ]
question documentation

All 15 comments

I think the simplest method would be to use overrideAttrs and pass the new flags as you would pass any other change.

See makeFlags and makeFlagsArray.
https://nixos.org/nixpkgs/manual/#build-phase

I guess I'm misunderstanding something here. I always thought overrideAttrs would override the inputs how the package is called?

As in:

{ stdenv, pkgs, dependency }: # override "dependency"
mkDerivation { ... }

Also: makeFlags must be passed in the buildPhase, so I must override the buildPhase, am I right? But packages like dmenu or mutt do not have a buildPhase - how to override it then?

overrideAttrs overrides the arguments passed to mkDerivation, so it overrides what you put inside of mkDerivation { ... }.

makeFlags is a parameter of mkDerivation so if you update it, the buildPhase should take that into account.

The generic builder / stdenv.mkDerivation already defines phases https://nixos.org/nixpkgs/manual/#sec-stdenv-phases, so the buildPhase already exists.

In some cases we explicitly pass a buildPhase because we want to do things differently. In that case passing makeFlags won't work unless our new buildPhase takes that parameter in account.

Okay, I came up with this:

  optimizeForThisHost = pkg:
    pkgs.lib.overrideDerivation pkg (old: {
      buildPhase = ''
        makeFlagsArray=(CFLAGS="$CFLAGS -fPIC -O3 -march=native")
      '';
    });

but it overrides the CFLAGS and removes the old ones (despite I use $CFLAGS in there).
Using overrideAttrs did not work:

  optimizeForThisHost = pkg:
    pkg.overrideAttrs (old: {
      makeFlags = ''${old.makeFlags} CFLAGS="$CFLAGS -fPIC -O3 -march=native'';
    });

results in error: attribute ‘makeFlags’ missing.

Does the package you test against have makeFlags defined? If it doesn't, then obviously old.makeFlags is going to error.

maybe use

makeFlags = [] ++ optionals (builtins.hasAttr 'makeFlags' old) [ "flag1" "flag2" ];

This just does not work as I want it to:

  optimizeForThisHost = pkg:
    pkg.overrideAttrs (old: {
      makeFlags = ["-fPIC" "-O3" "-march=native"] ++ # "CFLAGS='-fPIC -O3 -march=native'" doesn't work!
        (pkgs.stdenv.lib.optionals (builtins.hasAttr "makeFlags" old)) old.makeFlags;
        # I guess is this is what you meant with the snippet above
    });

gets me:

[...]
no configure script, doing nothing
building
make flags: SHELL=/nix/store/6yvwnldl0lzkx382ci7ljbqcg0yjg5gx-bash-4.4-p5/bin/bash -fPIC -O3 -march=native   
make: invalid option -- 'a'
make: invalid option -- 'c'
make: invalid option -- '='
make: invalid option -- 'a'
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Usage: make [options] [target] ...
Options:
[...]

ah, you want CFLAGS instead of make flags, my bad.
Just passing CFLAGS should be sufficient, however, it depends on how the configure script deals with it.
Judging from their script (if I get it correctly) they don't listen to what CFLAGS one passes.

Our compiler listens to NIX_CFLAGS_COMPILE. If you pass your flags via that env var it should be passed along. Note that what you see during building,

CFLAGS   = -std=c99 -pedantic -Wall -Os -I/usr/X11R6/include -I/usr/X11R6/include/freetype2 -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION="4.6" -DXINERAMA

is before the compiler actually gets to work and thus incorrect.

Note that what you see during building,
CFLAGS = -std=c99 -pedantic -Wall -Os -I/usr/X11R6/include -I/usr/X11R6/include/freetype2 -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION="4.6" -DXINERAMA
is before the compiler actually gets to work and thus incorrect.

I'm pretty sure that's not accurate, as the Makefile of dmenu prints it: http://git.suckless.org/dmenu/tree/Makefile#n11

exactly, which is before the compiler runs. Therefore NIX_CFLAGS_COMPILE aren't shown.

So, from what I understand, this snippet should be enough:

 pkgs.lib.overrideDerivation (pkgs.dmenu) (old: { NIX_CFLAGS_COMPILE = "-O3 -march=native"; })

but I have no way to check whether this gets actually passed to the compiler, as the Makefile does not print what exactly it is doing?


edit: When I pass pkgs.lib.overrideDerivation (pkgs.dmenu) (old: { NIX_CFLAGS_COMPILE = "FOO"; }) I get gcc: error: FOO: No such file or directory - so it seems to work as expected!

It seems to work as intended. Please leave this issue open, I will write up this for the documentation after my exam on thursday (or before, ... as procrastination for learning)!

Indeed, NIX_CFLAGS_COMPILE should be documented and any some more examples would be nice to have.

Closing this as #23123 is closed. Not sure whether it is in master, though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lverns picture lverns  Â·  3Comments

ayyess picture ayyess  Â·  3Comments

ghost picture ghost  Â·  3Comments

rzetterberg picture rzetterberg  Â·  3Comments

tomberek picture tomberek  Â·  3Comments