206 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { lib
 | |
| , stdenv
 | |
| , callPackage
 | |
| , dpkg
 | |
| , fetchurl
 | |
| , recurseIntoAttrs
 | |
| 
 | |
| , sqlite
 | |
| , elfutils
 | |
| }:
 | |
| 
 | |
| let
 | |
|   inherit (builtins)
 | |
|     elem attrNames attrValues concatMap filter fromJSON getAttr groupBy head isNull listToAttrs map mapAttrs readFile replaceStrings splitVersion ;
 | |
|   inherit (lib)
 | |
|     converge findFirst groupBy' hasPrefix optional pipe take toInt toList versionAtLeast versionOlder ;
 | |
| 
 | |
|   aptData = fromJSON (readFile ./packages.json);
 | |
| 
 | |
|   # Compare versions in debian control file syntax
 | |
|   # See: https://www.debian.org/doc/debian-policy/ch-relationships.html#syntax-of-relationship-fields
 | |
|   #
 | |
|   # NOTE: this is not a proper version comparison
 | |
|   #
 | |
|   # A proper version solver, should aggregate dependencies with the same name
 | |
|   # and compute the constraint (e.g. a (>= 2) a (<< 5) -> 2 <= a << 5)
 | |
|   #
 | |
|   # But in the intel repo, there are no such "duplicated" dependencies to specify
 | |
|   # upper limits, which leads to issues when intel-hpckit-2021 depends on things
 | |
|   # like intel-basekit >= 2021.1.0-2403 and we end up installing the newest
 | |
|   # basekit instead of the one from 2021.
 | |
|   #
 | |
|   # To mitigate this, >= is set to take the latest version with matching major
 | |
|   # and minor (only revision and patch are allowed to change)
 | |
|   compareVersions = got: kind: want:
 | |
|     let
 | |
|       g0 = take 2 (splitVersion got);
 | |
|       w0 = take 2 (splitVersion want);
 | |
|     in if isNull want then true
 | |
|     else if kind == "=" then got == want
 | |
|     else if kind == "<<" then versionOlder got want
 | |
|     else if kind == "<=" then versionAtLeast want got
 | |
|     else if kind == ">>" then versionOlder want got
 | |
|     else if kind == ">=" then (g0 == w0) && versionAtLeast got want # always match major version
 | |
|     else throw "unknown operation: ${kind}";
 | |
| 
 | |
|   findMatching = { pname, kind, version }:
 | |
|     findFirst (x: pname == x.pname && compareVersions x.version kind version) null aptData;
 | |
| 
 | |
|   isIntel = pkg: (hasPrefix "intel-" pkg.pname);
 | |
| 
 | |
|   expandDeps = pkg: (map findMatching (filter isIntel pkg.dependencies)) ++ (optional (pkg.size != 0) pkg);
 | |
| 
 | |
|   # get the oldest by major version. If they have the same major version, take
 | |
|   # the newest. This prevents most issues with resolutions
 | |
|   # versionOlder b a -> true if b is older than a (b `older` a)
 | |
|   getNewerInMajor = a: b: let
 | |
|     va = a.version;
 | |
|     vb = b.version;
 | |
|     va0 = head (splitVersion va);
 | |
|     vb0 = head (splitVersion vb);
 | |
|   in
 | |
|   if isNull a then b
 | |
|   else if va0 != vb0 then
 | |
|     if va0 > vb0 then b else a
 | |
|   else if versionOlder vb va then a else b;
 | |
|   removeDups = l: attrValues (groupBy' getNewerInMajor null (getAttr "provides") l);
 | |
| 
 | |
|   _resolveDeps = converge (l: removeDups (concatMap expandDeps l));
 | |
|   resolveDeps = pkg: let deps = _resolveDeps (toList pkg);
 | |
|       namedDeps = (map (x: "${x.pname}-${x.version}") deps);
 | |
|     in builtins.traceVerbose (builtins.deepSeq namedDeps namedDeps) deps;
 | |
| 
 | |
|   blacklist = [
 | |
|     "intel-basekit-env"
 | |
|     "intel-basekit-getting-started"
 | |
|     "intel-hpckit-env"
 | |
|     "intel-hpckit-getting-started"
 | |
|     "intel-oneapi-advisor"
 | |
|     "intel-oneapi-common-licensing"
 | |
|     "intel-oneapi-common-oneapi-vars"
 | |
|     "intel-oneapi-common-vars"
 | |
|     "intel-oneapi-compiler-cpp-eclipse-cfg"
 | |
|     "intel-oneapi-compiler-dpcpp-eclipse-cfg"
 | |
|     "intel-oneapi-condaindex"
 | |
|     "intel-oneapi-dev-utilities-eclipse-cfg"
 | |
|     "intel-oneapi-dpcpp-ct-eclipse-cfg"
 | |
|     "intel-oneapi-eclipse-ide"
 | |
|     "intel-oneapi-hpc-toolkit-getting-started"
 | |
|     "intel-oneapi-icc-eclipse-plugin-cpp"
 | |
|     "intel-oneapi-vtune"
 | |
|     "intel-oneapi-vtune-eclipse-plugin-vtune"
 | |
|   ];
 | |
| 
 | |
|   isInBlacklist = pkg: elem pkg.provides blacklist;
 | |
|   removeBlacklist = filter (e: !(isInBlacklist e));
 | |
| 
 | |
|   dpkgExtractAll = pname: version: {srcs, deps}: stdenv.mkDerivation {
 | |
|     inherit pname version srcs;
 | |
| 
 | |
|     nativeBuildInputs = [ dpkg ];
 | |
|     phases = [ "installPhase" ];
 | |
| 
 | |
|     passthru = { inherit deps; };
 | |
| 
 | |
|     installPhase = ''
 | |
|       mkdir -p $out
 | |
|       for src in $srcs; do
 | |
|         echo "Unpacking $src"
 | |
|         dpkg -x $src $out
 | |
|       done
 | |
|     '';
 | |
|   };
 | |
| 
 | |
|   apthost = "https://apt.repos.intel.com/oneapi/";
 | |
|   fetchDeb = p: fetchurl { url = apthost + p.filename; inherit (p) sha256; };
 | |
| 
 | |
|   buildIntel = pkg: pipe pkg [
 | |
|     resolveDeps
 | |
|     removeBlacklist
 | |
|     (l: {srcs = map fetchDeb l; deps = l; })
 | |
|     (dpkgExtractAll "${pkg.provides}-extracted" pkg.version)
 | |
|   ];
 | |
| 
 | |
|   findHpcKit = year: findMatching { pname = "intel-hpckit"; kind = "<<"; version = toString (year+1); };
 | |
|   years = map toInt (attrNames components);
 | |
| 
 | |
|   patchIntel = callPackage ./patch_intel.nix { };
 | |
| 
 | |
|   # Version information for each hpckit. This is used to normalize the paths
 | |
|   # so that files are in $out/{bin,lib,include...} instead of all over the place
 | |
|   # in $out/opt/intel/oneapi/*/*/{...}.
 | |
|   #
 | |
|   # The most important is the compiler component, which is used to build the
 | |
|   # stdenv for the hpckit.
 | |
|   #
 | |
|   # NOTE: this have to be manually specified, so we can avoid IFD. To add a
 | |
|   # new version, add a new field with an empty attrset, (e.g. "2026" = {}; ),
 | |
|   # build hpckit_2026.unpatched and use the values from
 | |
|   # result/opt/intel/oneapi/* to populate the attrset.
 | |
|   #
 | |
|   # WARN: if there are more than one version in the folders of the unpatched
 | |
|   # components, our dependency resolution hacks have probably failed and the
 | |
|   # package set may be broken.
 | |
|   components = {
 | |
|     "2025" = {
 | |
|       ishmem = "1.3";
 | |
|       pti = "0.12";
 | |
|       tcm = "1.3";
 | |
|       umf = "0.10";
 | |
| 
 | |
|       ccl = "2021.15";
 | |
|       compiler = "2025.1";
 | |
|       dal = "2025.5";
 | |
|       debugger = "2025.1";
 | |
|       dev-utilities = "2025.1";
 | |
|       dnnl = "2025.1";
 | |
|       dpcpp-ct = "2025.1";
 | |
|       dpl = "2022.8";
 | |
|       ipp = "2022.1";
 | |
|       ippcp = "2025.1";
 | |
|       mkl = "2025.1";
 | |
|       mpi = "2021.15";
 | |
|       tbb = "2022.1";
 | |
|     };
 | |
|     "2024" = {
 | |
|       tcm = "1.1";
 | |
| 
 | |
|       ccl = "2021.13";
 | |
|       compiler = "2024.2";
 | |
|       dal = "2024.6";
 | |
|       debugger = "2024.2";
 | |
|       dev-utilities = "2024.2";
 | |
|       diagnostics = "2024.2";
 | |
|       dnnl = "2024.2";
 | |
|       dpcpp-ct = "2024.2";
 | |
|       dpl = "2022.6";
 | |
|       ipp = "2021.12";
 | |
|       ippcp = "2021.12";
 | |
|       mkl = "2024.2";
 | |
|       mpi = "2021.13";
 | |
|       tbb = "2021.13";
 | |
| 
 | |
|       extraPackages = [
 | |
|         sqlite
 | |
|         elfutils
 | |
|       ];
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   replaceDots = replaceStrings ["."] ["_"];
 | |
| 
 | |
| in recurseIntoAttrs (listToAttrs (map (year: let
 | |
|       year_str = toString year;
 | |
|     in {
 | |
|       name = "hpckit_${year_str}";
 | |
|       value = patchIntel {unpatched = buildIntel (findHpcKit year); components = components.${year_str}; };
 | |
|   }) years)) // {
 | |
|   apt = pipe aptData [
 | |
|     (groupBy (p: replaceDots p.provides))
 | |
|     (mapAttrs (_: l: listToAttrs (map (pkg: { name = replaceDots ("v" + pkg.version); value = pkg; }) l)))
 | |
|   ] ;
 | |
| 
 | |
|   inherit resolveDeps patchIntel buildIntel;
 | |
| }
 |