Does `enableParallelBuilding` Do anything?

Hey I’m working on a mid size nix package that compiles a few sub modules it requires. I removed my -j16s from my package and enabled enableParallelBuilding and I noticed the build time was much much slower and on btop my cpu was not fully used, I can’t find much info about this option online. Likely because this is a nixpkg option and not a nixos option.

1 Like

Depends on how you used it.

g++ and ld basically, I should say I posted this because I’ve seen g++ use all my cores, I just don’t know why this option doesn’t enable it.

I guess I was too subtle - please post your nix code, otherwise we are just guessing.

No prob, also I’ll post an error if you could help.

{ lib
, stdenv
, fetchFromGitHub
, # build deps
  premake5
, writeShellScriptBin
, runCommandLocal
, symlinkJoin
, imagemagick
, # edopro deps
  bzip2
, curl
, flac
, fmt_9
, freetype
, libevent
, libgit2
, libGL
, libGLU
, libjpeg
, libpng
, libvorbis
, libXxf86vm
, lua5_3
, nlohmann_json
, noto-fonts-cjk-sans
, openal
, SDL2
, SDL2_mixer
, sqlite
, # Irrlicht deps
  wayland
, egl-wayland
, libxkbcommon
, libX11
,
}:
let
  # the assets repo has a font instead
  font = "${noto-fonts-cjk-sans}/share/fonts/opentype/noto-cjk/NotoSansCJK-VF.otf.ttc";

  assets = {
    pname = "assets";
    version = "20230104";

    src = fetchFromGitHub {
      owner = "ProjectIgnis";
      repo = "Distribution";
      rev = "3be220c4f47c7d45b97657bd37ce37c7c6935398";
      hash = "sha256-w2Vhnf32lKVDLyosvw74LzDLuxr3hfVILVSkyro1/8o=";
    };
  };

  irrlicht-edopro = stdenv.mkDerivation {
    pname = "irrlicht-edopro";
    version = "1.9-custom";

    src = fetchFromGitHub {
      owner = "edo9300";
      repo = "irrlicht1-8-4";
      rev = "7edde28d4f8c0c3589934c398a3a441286bb7c22";
      hash = "sha256-Q2tNiYE/enZPqA5YhUe+Tkvmqtmmz2E0OqTRUDnt+UA=";
    };

    buildInputs = [
      libGLU
      libX11
      libXxf86vm
      wayland
      libxkbcommon
    ];

    enableParallelBuilding = true;
    preBuild = ''
      makeFlagsArray+=(sharedlib NDEBUG=1)
      make -C source/Irrlicht
    '';

    installPhase = ''
      mkdir -p $out/{bin,include}
      cp -r include/* $out/include
      cp lib/Linux/libIrrlicht.a $out/bin
    '';
  };

  ocgcore = stdenv.mkDerivation rec {
    pname = "ygopro-core";
    version = "4a872ad7686e0d00ee4c1c051e90fc07c40613d4";

    src = fetchFromGitHub {
      owner = "edo9300";
      repo = pname;
      rev = version;
      hash = "sha256-s3DOHrZilRUy6fbXObNiLRinxpdHY99vDOmS/ZfOI78=";
    };

    nativeBuildInputs = [ premake5 ];

    buildInputs = [ lua5_3 ];

    enableParallelBuilding = true;
    buildFlags = [ "config=release" ];
    preBuild = ''
      premake5 gmake2

      make -C build
    '';

    installPhase = ''
      mkdir -p $out/{bin,lib}
      cp bin/debug/libocgcore.a $out/bin
      cp bin/debug/libocgcore.so $out/lib
    '';
  };

  edopro = stdenv.mkDerivation rec {
    pname = "edopro";
    version = "40.1.4";

    src = fetchFromGitHub {
      owner = "edo9300";
      repo = pname;
      rev = version;
      hash = "sha256-2E1cjG0FONu/fbr67/3qRCKQ1W/wPznClEWsMa1FAzo=";
      fetchSubmodules = true;
    };

    nativeBuildInputs = [ premake5 ];

    buildInputs = [
      bzip2
      curl
      flac
      fmt_9
      freetype
      irrlicht-edopro
      libevent
      libgit2
      libjpeg
      libpng
      libvorbis
      lua5_3
      nlohmann_json
      openal
      SDL2
      SDL2_mixer
      sqlite
    ];

    # nixpkgs' gcc stack currently appears to not support LTO
    #postPatch = ''
    #  sed -i '/LinkTimeOptimization/d' ./premake5.lua
    #'';

    # Edopro normally builds irrlicht without a prefix in its include
    # dir
    NIX_CFLAGS_COMPILE = ''
      -I${irrlicht-edopro}/include
      -l${irrlicht-edopro}/bin
      -l${ocgcore}/bin
    '';


    enableParallelBuilding = true;
    buildFlags = [ "verbose=true config=release_x64 ygoprodll" ];
    preBuild = ''
      premake5 gmake2 \
        --architecture=x64 \
        --no-core \
        --bundled-font='${font}'

      make -C build
    '';

    installPhase = ''
      mkdir -p $out/bin
      cp bin/x64/release/ygoprodll $out/bin
    '';
  };

  edopro-script =
    let
      assetsToCopy = lib.concatStringsSep "," [
        "config"
        "deck"
        "expansions"
        "lflists"
        "puzzles"
        "fonts"
        "script"
        "skin"
        "sound"
        "textures"
      ];
    in
    # this doesn't create the config files? but it does set ld library?
    writeShellScriptBin "EDOPro" ''
      set -eu
      EDOPRO_DIR="''${XDG_DATA_HOME:-~/.local/share}/edopro"

      if [ ! -d "''${EDOPRO_DIR}" ]; then
          mkdir -p "''${EDOPRO_DIR}"
          cp -r ${assets.src}/{${assetsToCopy}} "''${EDOPRO_DIR}/"

          find "''${EDOPRO_DIR}" -type d -exec chmod u=rwx,go-rwx {} +
          find "''${EDOPRO_DIR}" -type f -exec chmod u=rw,go-rwx {} +

      fi

      export LD_LIBRARY_PATH='${
        lib.makeLibraryPath [
          egl-wayland
          libGL
          libX11
          libxkbcommon
          libXxf86vm
          wayland
        ]
      }';

      exec ${edopro}/bin/ygoprodll -C "''${EDOPRO_DIR}" $@
    '';
in
symlinkJoin {
  name = "edopro-application";
  paths = [
    edopro
    edopro-script
  ];

  postBuild = ''
  '';
}
error: builder for '/nix/store/3ynzm7dfc2qn2z26nwxljygrjmxl1bpw-edopro-40.1.4.drv' failed with exit code 2;
       last 10 log lines:
       > windbot_panel.cpp
       > Linking ygopro
       > /nix/store/x7yyxvwy1f9hlx72rzrgx069jyf7hxwr-binutils-2.42/bin/ld: cannot find -locgcore: No such file or directory
       > /nix/store/x7yyxvwy1f9hlx72rzrgx069jyf7hxwr-binutils-2.42/bin/ld: cannot find -lIrrlicht: No such file or directory
       > /nix/store/x7yyxvwy1f9hlx72rzrgx069jyf7hxwr-binutils-2.42/bin/ld: cannot find -l/nix/store/v8h09v3l1hnl27h37av3apgpqvl7rvg7-irrlicht-edopro-1.9-custom/bin: No such file or directory
       > /nix/store/x7yyxvwy1f9hlx72rzrgx069jyf7hxwr-binutils-2.42/bin/ld: cannot find -l/nix/store/1mdrhhm7vi45y73b2g9lrj0l7mh08x4r-ygopro-core-4a872ad7686e0d00ee4c1c051e90fc07c40613d4/bin: No such file or directory
       > collect2: error: ld returned 1 exit status
       > make[1]: *** [ygopro.make:199: ../bin/x64/debug/ygopro] Error 1
       > make: *** [Makefile:40: ygopro] Error 2
       > make: Leaving directory '/build/source/build'
       For full logs, run 'nix log /nix/store/3ynzm7dfc2qn2z26nwxljygrjmxl1bpw-edopro-40.1.4.drv'.
error: 1 dependencies of derivation '/nix/store/5vhjliavk6z3zlkxiswz7abh626ii37d-edopro-application.drv' failed to build

nixpkgs on  3dopolololo [!+?] took 3m32s 
❯ ls -lah /nix/store/v8h09v3l1hnl27h37av3apgpqvl7rvg7-irrlicht-edopro-1.9-custom/bin
total 16M
dr-xr-xr-x 2 root root 4.0K Dec 31  1969 .
dr-xr-xr-x 4 root root 4.0K Dec 31  1969 ..
-r--r--r-- 3 root root  16M Dec 31  1969 libIrrlicht.a

nixpkgs on  3dopolololo [!+?] 
❯ ls -lah /nix/store/1mdrhhm7vi45y73b2g9lrj0l7mh08x4r-ygopro-core-4a872ad7686e0d00ee4c1c051e90fc07c40613d4/bin
total 2.2M
dr-xr-xr-x 2 root root 4.0K Dec 31  1969 .
dr-xr-xr-x 4 root root 4.0K Dec 31  1969 ..
-r--r--r-- 3 root root 2.2M Dec 31  1969 libocgcore.a

Nix sets NIX_BUILD_CORES in derivations to the cores setting from nix.conf, which can also be specified on the CLI with --cores. Note that this is different from --max-jobs / -j, which controls how many separate derivations can be built at once. Many builders, such as the default make builder with stdenv.mkDerivation, will pass NIX_BUILD_CORES to the appropriate build tool to use more cores, but only if enableParallelBuilding is enabled.

2 Likes

This seems suspicious on two fronts:

  • gmake2, whatever that is, might not be using the parallel building attribute
  • you have make in preBuild, that’s going to run twice (and the way you specified it it won’t respect the makeFlags the first time through)

I also find it odd that you’re setting NIX_CFLAGS_COMPILE manually

1 Like

Why does it not default to something like nproc?

cores = 0 is the default, in which case yes Nix will set it to the number of cores. But nixpkgs sets enableParallelBuilding to false by default because parallelism is a common source of nondeterminism, which can make builds non-reproducible. It’s easy enough to flip that this is the better default.

1 Like

Is there a way to run make once with -C? This was the only way I found besides adding a cd which made the rest of this a nightmare with being in the source directory.

Okay thanks, I thought this might be like nixpkgs.config.rocmSupport where once it’s enabled some packages manually compile even on the stable channel.

After looking at it closer I believe a lot of my makeflags aren’t actually being passed to make

As @waffle8946 mentioned, that’s because you’re calling make manually without any flags. Stop doing that.

1 Like

Maybe I misunderstand but if buildphase is empty on the stdenv.mkder will assume the build phase is just make? Also whats a good way to store make flags vs build flags.

stdenv.mkDerivation uses makeFlags and buildFlags when calling make. You forgot to do that.
Also, you set preBuild, not buildPhase, so it will run make twice.

You can just set makeFlags or buildFlags instead of calling make manually in the first place.

3 Likes

Thank you I refactored my package to do that, but now I get a linking problem

cc1plus: note: unrecognized command-line option '-Wno-unknown-warning-option' may have been intended to silence earlier diagnostics
Linking ygoprodll
/nix/store/x7yyxvwy1f9hlx72rzrgx069jyf7hxwr-binutils-2.42/bin/ld: cannot find -lIrrlicht: No such file or directory
collect2: error: ld returned 1 exit status
make[1]: *** [ygoprodll.make:139: ../bin/x64/release/ygoprodll] Error 1
make: *** [Makefile:59: ygoprodll] Error 2
make: Leaving directory '/build/source/build'
error: builder for '/nix/store/3k1dlqq5lq0c9whgqzrs1z8f9izhrzir-edopro-40.1.4.drv' failed with exit code 2;
{ lib
, stdenv
, fetchFromGitHub
, # build deps
  premake5
, writeShellScriptBin
, runCommandLocal
, symlinkJoin
, imagemagick
, # edopro deps
  bzip2
, curl
, flac
, fmt_9
, freetype
, libevent
, libgit2
, libGL
, libGLU
, libjpeg
, libpng
, libvorbis
, libXxf86vm
, lua5_3
, nlohmann_json
, noto-fonts-cjk-sans
, openal
, SDL2
, sfml
, sqlite
, # Irrlicht deps
  wayland
, egl-wayland
, libxkbcommon
, libX11
,
}:
let
  # the assets repo has a font instead
  font = "${noto-fonts-cjk-sans}/share/fonts/opentype/noto-cjk/NotoSansCJK-VF.otf.ttc";

  assets = {
    pname = "assets";
    version = "40.1.4";

    src = fetchTarball {
      url = "https://github.com/ProjectIgnis/edopro-assets/releases/download/40.1.4/ProjectIgnis-EDOPro-40.1.4-linux.tar.gz";
      sha256 = "sha256-vZhkWJ1ZoNEwdc5kM1S0hyXnWmupiTOanCi9DCuqw/k=";
    };
  };

  irrlicht-edopro = stdenv.mkDerivation {
    pname = "irrlicht-edopro";
    version = "1.9-custom";

    src = fetchFromGitHub {
      owner = "edo9300";
      repo = "irrlicht1-8-4";
      rev = "7edde28d4f8c0c3589934c398a3a441286bb7c22";
      hash = "sha256-Q2tNiYE/enZPqA5YhUe+Tkvmqtmmz2E0OqTRUDnt+UA=";
    };

    buildInputs = [
      libGLU
      libX11
      libxkbcommon
      libXxf86vm
      wayland
    ];

    enableParallelBuilding = true;
    # Dynamic linking causes compile errors so we statically link.
    # However it can be reenabled with adding `sharedlib` to `buildFlags`.
    buildFlags = "NDEBUG=1";
    makeFlags = "-C source/Irrlicht -j16";

    installPhase = ''
        mkdir -p $out/{bin,include}
        cp lib/Linux/libIrrlicht.a $out/bin
        cp -r include/* $out/include

       ls -lah lib/Linux/
    '';
  };

  edopro = stdenv.mkDerivation rec {
    pname = "edopro";
    version = "40.1.4";

    src = fetchFromGitHub {
      owner = "edo9300";
      repo = pname;
      rev = version;
      hash = "sha256-2E1cjG0FONu/fbr67/3qRCKQ1W/wPznClEWsMa1FAzo=";
      fetchSubmodules = true;
    };

    nativeBuildInputs = [ premake5 ];

    buildInputs = [
      bzip2
      curl
      flac
      fmt_9
      freetype
      irrlicht-edopro
      libevent
      libgit2
      libjpeg
      libpng
      libvorbis
      lua5_3
      nlohmann_json
      openal
      SDL2
      sfml
      sqlite
    ];

    # nixpkgs' gcc stack currently appears to not support LTO
    postPatch = ''
      sed -i '/LinkTimeOptimization/d' ./premake5.lua
    '';

    # TODO sound
    preBuild = ''
      premake5 gmake2 \
        --architecture=x64 \
        --bundled-font='${font}'
    '';

    enableParallelBuilding = true;
    buildFlags = "-I ${irrlicht-edopro}/include -L ${irrlicht-edopro}/bin config=release_x64 ygoprodll"; # <---
    makeFlags = "-C build -j16";

    installPhase = ''
      ls -lah bin/x64
      ls -lah bin/x64/release
      mkdir -p $out/{bin,lib}
      cp bin/x64/release/ygoprodll $out/bin
      cp bin/x64/release/*.a $out/lib
    '';
  };

  edopro-script =
    let
      assetsToCopy = lib.concatStringsSep "," [
        "config"
        "deck"
        "COPYING.txt"
        "expansions"
        # We grab the ocgcore from the official release bundle, on
        # upstream suggestion; this is completely static and has no
        # dependencies, so it should be fine.
        "libocgcore.so"
        "lflists"
        "notices"
        "puzzles"
        "fonts"
        "script"
        "skin"
        "sound"
        "textures"
      ];
    in
    writeShellScriptBin "EDOPro" ''
      set -eu
      EDOPRO_DIR="''${XDG_DATA_HOME:-~/.local/share}/edopro"

      if [ ! -d "''${EDOPRO_DIR}" ]; then
          mkdir -p "''${EDOPRO_DIR}"
          cp -r ${assets.src}/{${assetsToCopy}} "''${EDOPRO_DIR}/"

          find "''${EDOPRO_DIR}" -type d -exec chmod u=rwx,go-rwx {} +
          find "''${EDOPRO_DIR}" -type f -exec chmod u=rw,go-rwx {} +

          rm "''${EDOPRO_DIR}/config/io.github.edo9300.EDOPro.desktop.in"
      fi
      ls -lah "''${EDOPRO_DIR}"

      export LD_LIBRARY_PATH='${
        lib.makeLibraryPath [
          egl-wayland
          libGL
          libX11
          libxkbcommon
          libXxf86vm
          wayland
        ]
      }';

      exec ${edopro}/bin/ygoprodll -C "''${EDOPRO_DIR}" $@
    '';

  edopro-desktop = runCommandLocal "io.github.edo9300.EDOPro.desktop" { } ''
    ls -lah ${assets.src}
    ls -lah  ${assets.src}/config
    cp ${assets.src}/config/io.github.edo9300.EDOPro.desktop.in desktop-template

    sed '/Path=/d' -i desktop-template
    sed 's/Exec=.*/Exec=EDOPro/' -i desktop-template
    sed 's/Icon=.*/Icon=EDOPro/' -i desktop-template

    install -D desktop-template $out/share/applications/io.github.edo9300.EDOPro.desktop
  '';
in
symlinkJoin {
  name = "edopro-application";
  paths = [
    edopro
    edopro-script
    edopro-desktop
  ];

  postBuild = ''
    mkdir -p $out/share/icons/hicolor/256x256/apps/
    ${imagemagick}/bin/magick \
        ${assets.src}/textures/AppIcon.png \
        -resize 256x256 \
        $out/share/icons/hicolor/256x256/apps/EDOPro.png
  '';
}

This is very weird because I’ve tripped checked that the required archive file is there, its just not being passed with -L to gcc for some reason, I’m unsure why.

The problem here was buildflags are not cflags passed to gcc, they are append onto the end of make.

1 Like