diff --git a/pkgs/development/libraries/intel-oneapi/base.nix b/pkgs/development/libraries/intel-oneapi/base.nix index 5d4c6fc28e67..f3b272b3b9f3 100644 --- a/pkgs/development/libraries/intel-oneapi/base.nix +++ b/pkgs/development/libraries/intel-oneapi/base.nix @@ -1,5 +1,6 @@ { lib, + callPackage, fetchurl, zlib, rdma-core, @@ -7,7 +8,6 @@ ucx, numactl, level-zero, - pkg-config, libdrm, elfutils, libxxf86vm, @@ -42,7 +42,7 @@ fontconfig, libuuid, sqlite, - + libffi, # 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" ] @@ -55,13 +55,7 @@ "intel.oneapi.lin.vtune" "intel.oneapi.lin.mkl.devel" ], - intel-oneapi, - - # For tests - runCommand, - libffi, - stdenv, }: intel-oneapi.mkIntelOneApi (finalAttrs: { pname = "intel-oneapi-base-toolkit"; @@ -189,62 +183,9 @@ intel-oneapi.mkIntelOneApi (finalAttrs: { 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 - ''; + passthru.stdenv = callPackage ./stdenv.nix { kit = intel-oneapi.base; }; - nativeBuildInputs = [ - pkg-config - ]; - buildInputs = [ intel-oneapi.base ]; - - 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.base}/mpi/latest" - for bin in "${intel-oneapi.base}"/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" - ''; - }; + passthru.tests = callPackage ./tests.nix { kit = intel-oneapi.base; }; meta = { description = "Intel oneAPI Base Toolkit"; diff --git a/pkgs/development/libraries/intel-oneapi/stdenv.nix b/pkgs/development/libraries/intel-oneapi/stdenv.nix new file mode 100644 index 000000000000..f813889df3e8 --- /dev/null +++ b/pkgs/development/libraries/intel-oneapi/stdenv.nix @@ -0,0 +1,58 @@ +{ + kit, + stdenvNoCC, + stdenv, + overrideCC, + wrapCCWith, +}: +let + unwrappedCC = stdenvNoCC.mkDerivation { + name = "intel-oneapi-cc-unwrapped"; + dontUnpack = true; + + # Note: use a wrapper script, not symlinks. The compiler inspects argv[0] + # to decide how to behave, so it must see itself invoked as + # icx/icpx. Through a symlink it would see clang/clang++ and + # select the wrong behavior. + installPhase = '' + mkdir -p $out/bin + + cat > $out/bin/clang++ << 'EOF' + #!/bin/sh + exec ${kit}/compiler/latest/bin/icpx "$@" + EOF + chmod +x $out/bin/clang++ + + cat > $out/bin/clang << 'EOF' + #!/bin/sh + exec ${kit}/compiler/latest/bin/icx "$@" + EOF + chmod +x $out/bin/clang + ''; + + passthru.isClang = true; + + # icpx rejects these flags for the SPIR-V device target (spir64-unknown-unknown). + hardeningUnsupportedFlags = [ + "zerocallusedregs" + "pacret" + "shadowstack" + ]; + }; + + wrappedCC = wrapCCWith { + cc = unwrappedCC; + extraPackages = [ kit ]; + extraBuildCommands = '' + # Consumers expect the icpx/icx names and might reject clang++/clang. + ln -s $out/bin/clang++ $out/bin/icpx + ln -s $out/bin/clang $out/bin/icx + + echo "export CXX=\"$out/bin/icpx\"" >> $out/nix-support/setup-hook + echo "export CC=\"$out/bin/icx\"" >> $out/nix-support/setup-hook + + echo "export ONEAPI_ROOT=\"${kit}\"" >> $out/nix-support/setup-hook + ''; + }; +in +overrideCC stdenv wrappedCC diff --git a/pkgs/development/libraries/intel-oneapi/test.c b/pkgs/development/libraries/intel-oneapi/test.c deleted file mode 100644 index 9413ac0c68e9..000000000000 --- a/pkgs/development/libraries/intel-oneapi/test.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#include - -int main() { - float u[] = {1., 2., 3.}; - float v[] = {4., 5., 6.}; - - float dp = cblas_sdot(3, u, 1, v, 1); - - assert(dp == 32.); -} diff --git a/pkgs/development/libraries/intel-oneapi/tests.nix b/pkgs/development/libraries/intel-oneapi/tests.nix new file mode 100644 index 000000000000..d206a48c87f5 --- /dev/null +++ b/pkgs/development/libraries/intel-oneapi/tests.nix @@ -0,0 +1,130 @@ +{ + kit, + stdenv, + runCommand, + pkg-config, + writeText, +}: +{ + mkl-libs = stdenv.mkDerivation { + name = "intel-oneapi-test-mkl-libs"; + src = writeText "test.c" '' + #include + #include + int main() { + float u[] = {1., 2., 3.}; + float v[] = {4., 5., 6.}; + float dp = cblas_sdot(3, u, 1, v, 1); + assert(dp == 32.); + } + ''; + dontUnpack = true; + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ kit ]; + buildPhase = '' + # This will fail if no libs with mkl- in their name are found + libs="$(pkg-config --list-all | cut -d\ -f1 | grep mkl-)" + [ -n "$libs" ] || { echo "No MKL libs found via pkg-config" >&2; exit 1; } + for lib in $libs; do + echo "Testing that the build succeeds with $lib" >&2 + gcc $src -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-oneapi: 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="${kit}/mpi/latest" + for bin in "${kit}"/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" + ''; + + sycl-compile = kit.stdenv.mkDerivation { + name = "intel-oneapi-test-sycl-compile"; + src = writeText "test.cpp" '' + #include + #include + int main() { + // We likely won't have a SYCL device available, + // due to the nix sandbox, but this test only + // verifies that SYCL compiles, so we don't need a device + try { + sycl::queue q; + std::cout << q.get_device().get_info() << std::endl; + } catch (const sycl::exception& e) { + std::cerr << "No SYCL device found: " << e.what() << std::endl; + } + return 0; + } + ''; + dontUnpack = true; + buildPhase = "icpx -fsycl $src -o test"; + doCheck = true; + checkPhase = "./test"; + installPhase = ''touch "$out"''; + }; + + headers-available = kit.stdenv.mkDerivation { + name = "intel-oneapi-test-headers-available"; + dontUnpack = true; + buildPhase = '' + echo '#include ' | icpx -fsycl -x c++ -E - > /dev/null + echo '#include ' | icpx -fsycl -x c++ -E - > /dev/null + echo '#include ' | icpx -x c++ -E - > /dev/null + ''; + installPhase = ''touch "$out"''; + }; + + c-compile = kit.stdenv.mkDerivation { + name = "intel-oneapi-test-c-compile"; + src = writeText "test.c" '' + #include + int main() { printf("Hello from Intel C compiler!\n"); return 0; } + ''; + dontUnpack = true; + buildPhase = "icx $src -o test"; + doCheck = true; + checkPhase = "./test"; + installPhase = ''touch "$out"''; + }; + + openmp-compile = kit.stdenv.mkDerivation { + name = "intel-oneapi-test-openmp-compile"; + src = writeText "test.c" '' + #include + #include + int main() { + #pragma omp parallel + { printf("Hello from thread %d\n", omp_get_thread_num()); } + return 0; + } + ''; + dontUnpack = true; + buildPhase = "icx -fiopenmp $src -o test"; + doCheck = true; + checkPhase = "./test"; + installPhase = ''touch "$out"''; + }; +}