Unverified Commit 66e2080e authored by Alexander Bantyev's avatar Alexander Bantyev
Browse files

intel-oneapi.{base,hpc}: init at 2025.2.1.44

Introduces the two freeware Intel's OneApi toolkits.

The Intel® oneAPI Base Toolkit (Base Kit) is a core set of tools and
libraries for developing high-performance, data-centric applications
across diverse architectures. It features an industry-leading C++
compiler that implements SYCL*, an evolution of C++ for heterogeneous
computing.

Intel® oneAPI HPC Toolkit delivers what developers need to build,
analyze, optimize, and scale HPC (high-performance computing)
applications with the latest techniques in vectorization,
multithreading, multi-node parallelization, and memory optimization.

They are packaged from official "offline" installers, which require
some wrangling to get working due to their reliance on FHS. The
resulting libraries and tools seem to work fine without FHS.
parent 6cfed029
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -786,6 +786,12 @@ lib.mapAttrs mkLicense (
      free = false;
    };

    intel-eula = {
      fullName = "Intel End User License Agreement for Developer Tools";
      url = "https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/WordDocuments/intelamtsdklicense.htm";
      free = false;
    };

    interbase = {
      spdxId = "Interbase-1.0";
      fullName = "Interbase Public License v1.0";
+254 −0
Original line number Diff line number Diff line
{
  lib,
  fetchurl,
  zlib,
  rdma-core,
  libpsm2,
  ucx,
  numactl,
  level-zero,
  pkg-config,
  libdrm,
  elfutils,
  xorg,
  glib,
  nss,
  nspr,
  dbus,
  at-spi2-atk,
  cups,
  gtk3,
  pango,
  cairo,
  mesa,
  expat,
  libxkbcommon,
  eudev,
  alsa-lib,
  ncurses5,
  bzip2,
  gdbm,
  libxcrypt-legacy,
  freetype,
  gtk2,
  gdk-pixbuf,
  fontconfig,
  libuuid,
  sqlite,

  # The list of components to install;
  # Either [ "all" ], [ "default" ], or a custom list of components.
  # If you want to install all default components plus an extra one, pass [ "default" <your extra components here> ]
  # Note that changing this will also change the `buildInputs` of the derivation.
  # The default value is not "default" because some of the components in the defualt set are currently broken.
  components ? [
    "intel.oneapi.lin.advisor"
    "intel.oneapi.lin.dpcpp-cpp-compiler"
    "intel.oneapi.lin.dpcpp_dbg"
    "intel.oneapi.lin.vtune"
    "intel.oneapi.lin.mkl.devel"
  ],

  intel-oneapi,

  # For tests
  runCommand,
  libffi,
  stdenv,
}:
intel-oneapi.mkIntelOneApi rec {
  pname = "intel-oneapi-base-toolkit";

  src = fetchurl {
    url = "https://registrationcenter-download.intel.com/akdlm/IRC_NAS/3b7a16b3-a7b0-460f-be16-de0d64fa6b1e/intel-oneapi-base-toolkit-2025.2.1.44_offline.sh";
    sha256 = "0fg4mcp6syhmp2fhariv3raxlikakvm557w7ppc9vfdsj4ji2md1";
  };

  versionYear = "2025";
  versionMajor = "2";
  versionMinor = "1";
  versionRel = "44";

  inherit components;

  # Figured out by looking at autoPatchelfHook failure output
  depsByComponent = rec {
    advisor = [
      libdrm
      zlib
      gtk2
      gdk-pixbuf
      at-spi2-atk
      glib
      pango
      gdk-pixbuf
      cairo
      fontconfig
      glib
      freetype
      xorg.libX11
      xorg.libXxf86vm
      xorg.libXext
      xorg.libxcb
      xorg.libXcomposite
      xorg.libXdamage
      xorg.libXfixes
      xorg.libXrandr
      nss
      dbus
      cups
      mesa
      expat
      libxkbcommon
      eudev
      alsa-lib
      ncurses5
      bzip2
      libuuid
      gdbm
      libxcrypt-legacy
      sqlite
      nspr
    ];
    dpcpp-cpp-compiler = [
      zlib
      level-zero
    ];
    dpcpp_dbg = [
      level-zero
      zlib
    ];
    dpcpp-ct = [ zlib ];
    mpi = [
      zlib
      rdma-core
      libpsm2
      ucx
      libuuid
      numactl
      level-zero
      libffi
    ];
    pti = [ level-zero ];
    vtune = [
      libdrm
      elfutils
      zlib
      xorg.libX11
      xorg.libXext
      xorg.libxcb
      xorg.libXcomposite
      xorg.libXdamage
      xorg.libXfixes
      xorg.libXrandr
      glib
      nss
      dbus
      at-spi2-atk
      cups
      gtk3
      pango
      cairo
      mesa
      expat
      libxkbcommon
      eudev
      alsa-lib
      at-spi2-atk
      ncurses5
      bzip2
      libuuid
      gdbm
      libxcrypt-legacy
      sqlite
      nspr
    ];
    mkl = mpi ++ pti;
  };

  autoPatchelfIgnoreMissingDeps = [
    # Needs to be dynamically loaded as it depends on the hardware
    "libcuda.so.1"
    # All too old, not in nixpkgs anymore
    "libffi.so.6"
    "libgdbm.so.4"
    "libopencl-clang.so.14"
  ];

  passthru.updateScript = intel-oneapi.mkUpdateScript {
    inherit pname;
    file = "base.nix";
    downloadPage = "https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html?packages=oneapi-toolkit&oneapi-toolkit-os=linux&oneapi-lin=offline";
  };

  passthru.tests = {
    mkl-libs = stdenv.mkDerivation {
      name = "intel-oneapi-test-mkl-libs";
      unpackPhase = ''
        cp ${./test.c} test.c
      '';

      nativeBuildInputs = [
        pkg-config
      ];
      buildInputs = [ intel-oneapi ];

      buildPhase = ''
        # This will fail if no libs with mkl- in their name are found
        libs="$(pkg-config --list-all | cut -d\  -f1 | grep mkl-)"
        for lib in $libs; do
          echo "Testing that the build succeeds with $lib" >&2
          gcc test.c -o test-with-$lib $(pkg-config --cflags --libs $lib)
        done
      '';

      doCheck = true;

      checkPhase = ''
        for lib in $libs; do
          echo "Testing that the executable built with $lib runs" >&2
          ./test-with-$lib
        done
      '';

      installPhase = ''
        touch "$out"
      '';
    };

    all-binaries-run = runCommand "intel-oneapi-test-all-binaries-run" { } ''
      # .*-32: 32-bit executables can't be properly patched by patchelf
      # IMB-.*: all fail with a weird "bad file descriptor" error
      # fi_info, fi_pingpong: exits with 1 even if ran with `--help`
      # gdb-openapi: Python not initialized
      # hydra_bstrap_proxy, hydra_nameserver, hydra_pmi_proxy: doesn't respect --help
      # mpirun: can't find mpiexec.hydra for some reason
      # sycl-ls, sycl-trace: doesn't respect --help
      regex_skip="(.*-32)|(IMB-.*)|fi_info|fi_pingpong|gdb-oneapi|hydra_bstrap_proxy|hydra_nameserver|hydra_pmi_proxy|mpirun|sycl-ls|sycl-trace"
      export I_MPI_ROOT="${intel-oneapi}/mpi/latest"
      for bin in "${intel-oneapi}"/bin/*; do
        if [[ "$bin" =~ $regex_skip ]] || [ ! -f "$bin" ] || [[ ! -x "$bin" ]]; then
          echo "skipping $bin"
          continue
        fi
        echo "trying to run $bin --help or -help"
        "$bin" --help || "$bin" -help
      done
      touch "$out"
    '';
  };

  meta = with lib; {
    description = "Intel oneAPI Base Toolkit";
    homepage = "https://software.intel.com/content/www/us/en/develop/tools/oneapi/base-toolkit.html";
    license = with lib.licenses; [
      intel-eula
      issl
      asl20
    ];
    maintainers = with lib.maintainers; [
      balsoft
    ];
    platforms = [ "x86_64-linux" ];
  };
}
+83 −0
Original line number Diff line number Diff line
{
  lib,
  fetchurl,

  # The list of components to install;
  # Either [ "all" ], [ "default" ], or a custom list of components.
  # If you want to install all default components plus an extra one, pass [ "default" <your extra components here> ]
  # Note that changing this will also change the `buildInputs` of the derivation.
  #
  # If you want other components listed of the toolkit, consider using intel-oneapi.base instead;
  # This are specifically the components that are not present there.
  components ? [
    "intel.oneapi.lin.dpcpp-cpp-compiler"
    "intel.oneapi.lin.ifort-compiler"
    "intel.oneapi.lin.mpi.devel"
    "intel.oneapi.lin.tbb.devel"
  ],

  intel-oneapi,
  zlib,
  rdma-core,
  libpsm2,
  ucx,
  libuuid,
  numactl,
  level-zero,
  libffi,
}:
intel-oneapi.mkIntelOneApi rec {
  pname = "intel-oneapi-hpc-toolkit";

  src = fetchurl {
    url = "https://registrationcenter-download.intel.com/akdlm/IRC_NAS/2d2a6686-ff06-44ce-baf0-ab84f8dafa89/intel-oneapi-hpc-toolkit-2025.2.1.44_offline.sh";
    sha256 = "1ys8s2nh6snjiz7aglag7awy12ww01z026hzcidzy68kxq71wba8";
  };

  versionYear = "2025";
  versionMajor = "2";
  versionMinor = "1";
  versionRel = "44";

  inherit components;

  depsByComponent = {
    mpi = [
      zlib
      rdma-core
      libpsm2
      ucx
      libuuid
      numactl
      level-zero
      libffi
    ];
    pti = [ level-zero ];
    ifort-compiler = [ ];
  };

  autoPatchelfIgnoreMissingDeps = [
    # Needs to be dynamically loaded as it depends on the hardware
    "libcuda.so.1"
  ];

  passthru.updateScript = intel-oneapi.mkUpdateScript {
    inherit pname;
    file = "hpc.nix";
    downloadPage = "https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html?packages=hpc-toolkit&hpc-toolkit-os=linux&hpc-toolkit-lin=offline";
  };

  meta = with lib; {
    description = "Intel oneAPI HPC Toolkit";
    homepage = "https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit.html";
    license = with lib.licenses; [
      intel-eula
      issl
      asl20
    ];
    maintainers = with lib.maintainers; [
      balsoft
    ];
    platforms = [ "x86_64-linux" ];
  };
}
+179 −0
Original line number Diff line number Diff line
{
  lib,
  callPackage,
  stdenv,
  ncurses5,
  bc,
  bubblewrap,
  autoPatchelfHook,
  python3,
  libgcc,
  glibc,
  writeShellScript,
  writeText,
  writeTextFile,
}:

{
  mkIntelOneApi =
    {
      pname,
      versionYear,
      versionMajor,
      versionMinor,
      versionRel,
      src,
      meta,
      depsByComponent ? { },
      postInstall ? "",
      components ? [ "default" ],
      ...
    }@args:
    let
      shortName = name: builtins.elemAt (lib.splitString "." name) 3;
    in
    stdenv.mkDerivation (
      fa:
      {
        version = "${fa.versionYear}.${fa.versionMajor}.${fa.versionMinor}.${fa.versionRel}";

        nativeBuildInputs = [
          # Installer wants tput
          ncurses5
          # Used to check if there's enough disk space
          bc
          bubblewrap

          autoPatchelfHook

          # For patchShebangs
          python3
        ];

        # autoPatchelfHook will add these libraries to RPATH as required
        buildInputs = lib.concatLists (
          map (
            comp:
            if comp == "all" || comp == "default" then
              lib.concatLists (builtins.attrValues depsByComponent)
            else
              depsByComponent.${shortName comp} or [ ]
          ) components
        );

        phases = [
          "installPhase"
          "fixupPhase"
        ];

        # See https://software.intel.com/content/www/us/en/develop/documentation/installation-guide-for-intel-oneapi-toolkits-linux/top/installation/install-with-command-line.html
        installPhase = ''
          runHook preInstall
          # The installer expects a writeable home directory, even if installing elsewhere
          export HOME="$(mktemp -d)"

          # The installer expects that the installation directory is already present
          mkdir -p "$out"

          # Required for the installer to find libstdc++
          export LD_LIBRARY_PATH="${lib.makeLibraryPath [ libgcc.lib ]}"

          # The installer is an insane four-stage rube goldberg machine:
          # 1. Our $src (bash script) unpacks install.sh (bash script)
          # 2. install.sh unpacks bootstrapper (dylinked binary with hardcoded interpreter in /lib)
          # 3. bootstrapper unpacks installer (dylinked binary with hardcoded interpreter and libraries in /lib)
          # 4. installer installs the actual components we need
          #
          # While stage 1 allows to "only extract", other stages always try running the next executable down, and remove stuff if they fail.
          # I'm afraid this is the cleanest solution for now.
          mkdir -p fhs-root/{lib,lib64}
          ln -s "${glibc}/lib/"* fhs-root/lib/
          ln -s "${glibc}/lib/"* fhs-root/lib64/
          bwrap \
            --bind fhs-root / \
            --bind /nix /nix \
            --ro-bind /bin /bin \
            --dev /dev \
            --proc /proc \
            bash "$src" \
              -a \
              --silent \
              --eula accept \
              --install-dir "$out" \
              --components ${lib.concatStringsSep ":" components}

          # Non-reproducible
          rm -rf "$out"/logs
          # This contains broken symlinks and doesn't seem to be useful
          rm -rf "$out"/.toolkit_linking_tool

          ln -s "$out/$versionYear.$versionMajor"/{lib,etc,bin,share,opt} "$out"

          runHook postInstall
        '';
      }
      // (builtins.removeAttrs args [
        "depsByComponent"
        "components"
      ])
    );

  mkUpdateScript =
    {
      pname,
      downloadPage,
      file,
    }:
    writeTextFile {
      name = "update-intel-oneapi";
      executable = true;
      text = ''
        #!/usr/bin/env nix-shell
        #!nix-shell -i bash -p curl jq htmlq common-updater-scripts

        download_page=${lib.escapeShellArg downloadPage}
        pname=${lib.escapeShellArg pname}
        nixpkgs="$(git rev-parse --show-toplevel)"
        packageDir="$nixpkgs/pkgs/by-name/in/intel-oneapi"
        file="$packageDir"/${lib.escapeShellArg file}

        echo 'Figuring out the download URL' >&2

        # Intel helpfully gives us a wget command to run so that we can download the toolkit installer, as part of their product page.
        # This variable will contain that command (wget https://...), we will extract the URL from it.
        wget_command="$(curl "$download_page" \
          | htmlq 'code' --text \
          | grep "wget.*$pname.*sh")"

        regex="wget (.*$pname.([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)_offline[.]sh)"
        if [[ "$wget_command" =~ $regex ]]; then
            url="''${BASH_REMATCH[1]}"
            versionYear="''${BASH_REMATCH[2]}"
            versionMajor="''${BASH_REMATCH[3]}"
            versionMinor="''${BASH_REMATCH[4]}"
            versionRel="''${BASH_REMATCH[5]}"
        else
            echo "'$wget_command' does not match the expected format $regex" >&2
            exit 1
        fi

        if [[ "$(grep 'url =' "$file")" =~ "$url" ]] && [[ "''${BASH_REMATCH[0]}" == "$url" ]]; then
            echo "The URL is the same ($url), skipping prefetch" >&2
            sha256="$(jq .sha256 < "$outFile")"
        else
            echo "The new download URL is $url, prefetching it to store" >&2
            sha256=$(nix-prefetch-url --quiet "$url")
        fi

        sed -i "s|versionYear = \".*\";|versionYear = \"$versionYear\";|" "$file"
        sed -i "s|versionMajor = \".*\";|versionMajor = \"$versionMajor\";|" "$file"
        sed -i "s|versionMinor = \".*\";|versionMinor = \"$versionMinor\";|" "$file"
        sed -i "s|versionRel = \".*\";|versionRel = \"$versionRel\";|" "$file"
        sed -i "s|url = \".*\";|url = \"$url\";|" "$file"
        sed -i "s|sha256 = \".*\";|sha256 = \"$sha256\";|" "$file"
      '';
    };

  base = callPackage ./base.nix { };
  hpc = callPackage ./hpc.nix { };
}