1use crate::platform::detection::PackageManager;
12
13pub fn map_package_name(generic_name: &str, pkg_mgr: PackageManager) -> String {
18 match pkg_mgr {
19 PackageManager::Apt => map_apt(generic_name),
20 PackageManager::Pacman => map_pacman(generic_name),
21 PackageManager::Dnf => map_dnf(generic_name),
22 PackageManager::Yum => map_yum(generic_name),
23 PackageManager::Zypper => map_zypper(generic_name),
24 PackageManager::Unknown => generic_name.to_string(),
25 }
26}
27
28pub fn map_package_names(generic_names: &[&str], pkg_mgr: PackageManager) -> Vec<String> {
30 generic_names
31 .iter()
32 .map(|name| map_package_name(name, pkg_mgr))
33 .collect()
34}
35
36pub fn has_mapping(generic_name: &str, pkg_mgr: PackageManager) -> bool {
38 let mapped = map_package_name(generic_name, pkg_mgr);
39 mapped != generic_name || get_known_packages().contains(&generic_name)
41}
42
43pub fn get_known_packages() -> &'static [&'static str] {
45 &[
46 "build-essential",
48 "gcc",
49 "g++",
50 "make",
51 "cmake",
52 "ninja-build",
53 "pkg-config",
54 "autoconf",
55 "automake",
56 "libtool",
57 "python3",
59 "python3-dev",
60 "python3-pip",
61 "python3-venv",
62 "python3-setuptools",
63 "python3-wheel",
64 "python3-numpy",
65 "rocminfo",
67 "rocprofiler",
68 "rocm-smi-lib",
69 "rocm-dev",
70 "rocm-libs",
71 "hip-runtime",
72 "librccl-dev",
74 "librccl1",
75 "rccl",
76 "rccl-dev",
77 "migraphx",
78 "migraphx-dev",
79 "half",
80 "miopen-hip",
81 "rocblas",
82 "libopenmpi-dev",
84 "openmpi-bin",
85 "openmpi",
86 "openmpi-devel",
87 "environment-modules",
88 "llvm-dev",
90 "clang",
91 "lld",
92 "lldb",
93 "libssl-dev",
94 "libffi-dev",
95 "zlib1g-dev",
96 "pciutils",
98 "mesa-utils",
99 "clinfo",
100 "libnuma-dev",
101 "numactl",
102 "hwloc",
103 "lshw",
104 "dmidecode",
105 "git",
107 "git-lfs",
108 "gh",
109 "wget",
111 "curl",
112 "gnupg",
113 "ca-certificates",
114 "rsync",
115 "ssh",
116 "libbz2-dev",
118 "liblzma-dev",
119 "libsqlite3-dev",
120 "libncurses-dev",
121 "libreadline-dev",
122 "uuid-dev",
123 "libgdbm-dev",
124 ]
125}
126
127macro_rules! pkg_map {
134 ($name:expr, { $($pat:pat => $val:expr),* $(,)? }) => {
135 match $name {
136 $($pat => $val.to_string(),)*
137 _ => $name.to_string(),
138 }
139 };
140}
141
142fn map_apt(name: &str) -> String {
147 match name {
149 "openmpi" => "openmpi-bin libopenmpi-dev".to_string(),
150 "hip-runtime" => "hip-runtime-amd".to_string(),
151 _ => name.to_string(),
152 }
153}
154
155fn map_pacman(name: &str) -> String {
160 pkg_map!(name, {
161 "build-essential" => "base-devel",
163 "g++" => "gcc",
164 "ninja-build" => "ninja",
165 "pkg-config" => "pkgconf",
166
167 "python3" => "python",
169 "python3-dev" => "python",
170 "python3-pip" => "python-pip",
171 "python3-venv" => "python",
172 "python3-setuptools" => "python-setuptools",
173 "python3-wheel" => "python-wheel",
174 "python3-numpy" => "python-numpy",
175
176 "hip-runtime" => "hip-runtime-amd",
178
179 "librccl-dev" => "rccl",
181 "librccl1" => "rccl",
182 "rccl-dev" => "rccl",
183 "migraphx-dev" => "migraphx",
184
185 "libopenmpi-dev" => "openmpi",
187 "openmpi-bin" => "openmpi",
188 "openmpi" => "openmpi",
189 "openmpi-devel" => "openmpi",
190
191 "llvm-dev" => "llvm",
193 "libssl-dev" => "openssl",
194 "libffi-dev" => "libffi",
195 "zlib1g-dev" => "zlib",
196
197 "mesa-utils" => "mesa-demos",
199 "libnuma-dev" => "numactl",
200
201 "gh" => "github-cli",
203
204 "ssh" => "openssh",
206
207 "libbz2-dev" => "bzip2",
209 "liblzma-dev" => "xz",
210 "libsqlite3-dev" => "sqlite",
211 "libncurses-dev" => "ncurses",
212 "libreadline-dev" => "readline",
213 "uuid-dev" => "util-linux",
214 "libgdbm-dev" => "gdbm",
215 })
216}
217
218fn map_dnf(name: &str) -> String {
223 pkg_map!(name, {
224 "build-essential" => "@development-tools",
226 "g++" => "gcc-c++",
227 "pkg-config" => "pkgconf",
228
229 "python3-dev" => "python3-devel",
231 "python3-venv" => "python3",
232
233 "rocm-smi-lib" => "rocm-smi",
235
236 "librccl-dev" => "rccl-devel",
238 "rccl-dev" => "rccl-devel",
239 "migraphx-dev" => "migraphx-devel",
240
241 "libopenmpi-dev" => "openmpi-devel",
243 "openmpi" => "openmpi openmpi-devel",
244 "openmpi-devel" => "openmpi-devel",
245
246 "llvm-dev" => "llvm-devel",
248 "libssl-dev" => "openssl-devel",
249 "libffi-dev" => "libffi-devel",
250 "zlib1g-dev" => "zlib-devel",
251
252 "mesa-utils" => "mesa-demos",
254 "libnuma-dev" => "numactl-devel",
255
256 "gnupg" => "gnupg2",
258 "ssh" => "openssh-clients",
259
260 "libbz2-dev" => "bzip2-devel",
262 "liblzma-dev" => "xz-devel",
263 "libsqlite3-dev" => "sqlite-devel",
264 "libncurses-dev" => "ncurses-devel",
265 "libreadline-dev" => "readline-devel",
266 "uuid-dev" => "libuuid-devel",
267 "libgdbm-dev" => "gdbm-devel",
268 })
269}
270
271fn map_yum(name: &str) -> String {
276 pkg_map!(name, {
277 "build-essential" => "@development-tools",
279 "g++" => "gcc-c++",
280 "pkg-config" => "pkgconf",
281
282 "python3-dev" => "python3-devel",
284 "python3-venv" => "python3",
285
286 "rocm-smi-lib" => "rocm-smi",
288
289 "librccl-dev" => "rccl-devel",
291 "rccl-dev" => "rccl-devel",
292 "migraphx-dev" => "migraphx-devel",
293
294 "libopenmpi-dev" => "openmpi-devel",
296 "openmpi" => "openmpi openmpi-devel",
297 "openmpi-devel" => "openmpi-devel",
298
299 "llvm-dev" => "llvm-devel",
301 "libssl-dev" => "openssl-devel",
302 "libffi-dev" => "libffi-devel",
303 "zlib1g-dev" => "zlib-devel",
304
305 "mesa-utils" => "mesa-demos",
307 "libnuma-dev" => "numactl-devel",
308
309 "gnupg" => "gnupg2",
311 "ssh" => "openssh-clients",
312
313 "libbz2-dev" => "bzip2-devel",
315 "liblzma-dev" => "xz-devel",
316 "libsqlite3-dev" => "sqlite-devel",
317 "libncurses-dev" => "ncurses-devel",
318 "libreadline-dev" => "readline-devel",
319 "uuid-dev" => "libuuid-devel",
320 "libgdbm-dev" => "gdbm-devel",
321 })
322}
323
324fn map_zypper(name: &str) -> String {
329 pkg_map!(name, {
330 "build-essential" => "patterns-devel-base-devel_basis",
332 "g++" => "gcc-c++",
333 "ninja-build" => "ninja",
334 "pkg-config" => "pkgconf",
335
336 "python3-dev" => "python3-devel",
338 "python3-venv" => "python3",
339
340 "rocm-smi-lib" => "rocm-smi",
342
343 "librccl-dev" => "rccl-devel",
345 "rccl-dev" => "rccl-devel",
346 "migraphx-dev" => "migraphx-devel",
347
348 "libopenmpi-dev" => "openmpi-devel",
350 "openmpi" => "openmpi openmpi-devel",
351 "openmpi-devel" => "openmpi-devel",
352
353 "llvm-dev" => "llvm-devel",
355 "libssl-dev" => "libopenssl-devel",
356 "libffi-dev" => "libffi-devel",
357 "zlib1g-dev" => "zlib-devel",
358
359 "mesa-utils" => "Mesa-demo",
361 "libnuma-dev" => "libnuma-devel",
362
363 "gnupg" => "gpg2",
365 "ssh" => "openssh",
366
367 "libbz2-dev" => "libbz2-devel",
369 "liblzma-dev" => "xz-devel",
370 "libsqlite3-dev" => "sqlite3-devel",
371 "libncurses-dev" => "ncurses-devel",
372 "libreadline-dev" => "readline-devel",
373 "uuid-dev" => "libuuid-devel",
374 "libgdbm-dev" => "gdbm-devel",
375 })
376}
377
378#[cfg(test)]
379mod tests {
380 use super::*;
381
382 #[test]
389 fn test_build_essential_apt() {
390 assert_eq!(
391 map_package_name("build-essential", PackageManager::Apt),
392 "build-essential"
393 );
394 }
395 #[test]
396 fn test_build_essential_pacman() {
397 assert_eq!(
398 map_package_name("build-essential", PackageManager::Pacman),
399 "base-devel"
400 );
401 }
402 #[test]
403 fn test_build_essential_dnf() {
404 assert_eq!(
405 map_package_name("build-essential", PackageManager::Dnf),
406 "@development-tools"
407 );
408 }
409 #[test]
410 fn test_build_essential_yum() {
411 assert_eq!(
412 map_package_name("build-essential", PackageManager::Yum),
413 "@development-tools"
414 );
415 }
416 #[test]
417 fn test_build_essential_zypper() {
418 assert_eq!(
419 map_package_name("build-essential", PackageManager::Zypper),
420 "patterns-devel-base-devel_basis"
421 );
422 }
423
424 #[test]
426 fn test_gplusplus_pacman() {
427 assert_eq!(map_package_name("g++", PackageManager::Pacman), "gcc");
428 }
429 #[test]
430 fn test_gplusplus_dnf() {
431 assert_eq!(map_package_name("g++", PackageManager::Dnf), "gcc-c++");
432 }
433
434 #[test]
436 fn test_pkg_config_pacman() {
437 assert_eq!(
438 map_package_name("pkg-config", PackageManager::Pacman),
439 "pkgconf"
440 );
441 }
442 #[test]
443 fn test_pkg_config_dnf() {
444 assert_eq!(
445 map_package_name("pkg-config", PackageManager::Dnf),
446 "pkgconf"
447 );
448 }
449
450 #[test]
452 fn test_ninja_build_pacman() {
453 assert_eq!(
454 map_package_name("ninja-build", PackageManager::Pacman),
455 "ninja"
456 );
457 }
458
459 #[test]
462 fn test_python3_pacman() {
463 assert_eq!(
464 map_package_name("python3", PackageManager::Pacman),
465 "python"
466 );
467 }
468 #[test]
469 fn test_python3_dev_pacman() {
470 assert_eq!(
471 map_package_name("python3-dev", PackageManager::Pacman),
472 "python"
473 );
474 }
475 #[test]
476 fn test_python3_dev_dnf() {
477 assert_eq!(
478 map_package_name("python3-dev", PackageManager::Dnf),
479 "python3-devel"
480 );
481 }
482 #[test]
483 fn test_python3_dev_zypper() {
484 assert_eq!(
485 map_package_name("python3-dev", PackageManager::Zypper),
486 "python3-devel"
487 );
488 }
489 #[test]
490 fn test_python3_pip_pacman() {
491 assert_eq!(
492 map_package_name("python3-pip", PackageManager::Pacman),
493 "python-pip"
494 );
495 }
496 #[test]
497 fn test_python3_venv_pacman() {
498 assert_eq!(
499 map_package_name("python3-venv", PackageManager::Pacman),
500 "python"
501 );
502 }
503
504 #[test]
507 fn test_hip_runtime_apt() {
508 assert_eq!(
509 map_package_name("hip-runtime", PackageManager::Apt),
510 "hip-runtime-amd"
511 );
512 }
513 #[test]
514 fn test_hip_runtime_pacman() {
515 assert_eq!(
516 map_package_name("hip-runtime", PackageManager::Pacman),
517 "hip-runtime-amd"
518 );
519 }
520 #[test]
521 fn test_rocm_smi_lib_dnf() {
522 assert_eq!(
523 map_package_name("rocm-smi-lib", PackageManager::Dnf),
524 "rocm-smi"
525 );
526 }
527
528 #[test]
531 fn test_librccl_dev_pacman() {
532 assert_eq!(
533 map_package_name("librccl-dev", PackageManager::Pacman),
534 "rccl"
535 );
536 }
537 #[test]
538 fn test_librccl_dev_dnf() {
539 assert_eq!(
540 map_package_name("librccl-dev", PackageManager::Dnf),
541 "rccl-devel"
542 );
543 }
544 #[test]
545 fn test_migraphx_dev_dnf() {
546 assert_eq!(
547 map_package_name("migraphx-dev", PackageManager::Dnf),
548 "migraphx-devel"
549 );
550 }
551 #[test]
552 fn test_migraphx_dev_pacman() {
553 assert_eq!(
554 map_package_name("migraphx-dev", PackageManager::Pacman),
555 "migraphx"
556 );
557 }
558
559 #[test]
562 fn test_libopenmpi_dev_pacman() {
563 assert_eq!(
564 map_package_name("libopenmpi-dev", PackageManager::Pacman),
565 "openmpi"
566 );
567 }
568 #[test]
569 fn test_libopenmpi_dev_dnf() {
570 assert_eq!(
571 map_package_name("libopenmpi-dev", PackageManager::Dnf),
572 "openmpi-devel"
573 );
574 }
575 #[test]
576 fn test_openmpi_apt() {
577 assert_eq!(
578 map_package_name("openmpi", PackageManager::Apt),
579 "openmpi-bin libopenmpi-dev"
580 );
581 }
582 #[test]
583 fn test_openmpi_dnf() {
584 assert_eq!(
585 map_package_name("openmpi", PackageManager::Dnf),
586 "openmpi openmpi-devel"
587 );
588 }
589
590 #[test]
593 fn test_llvm_dev_pacman() {
594 assert_eq!(map_package_name("llvm-dev", PackageManager::Pacman), "llvm");
595 }
596 #[test]
597 fn test_llvm_dev_dnf() {
598 assert_eq!(
599 map_package_name("llvm-dev", PackageManager::Dnf),
600 "llvm-devel"
601 );
602 }
603 #[test]
604 fn test_libssl_dev_pacman() {
605 assert_eq!(
606 map_package_name("libssl-dev", PackageManager::Pacman),
607 "openssl"
608 );
609 }
610 #[test]
611 fn test_libssl_dev_dnf() {
612 assert_eq!(
613 map_package_name("libssl-dev", PackageManager::Dnf),
614 "openssl-devel"
615 );
616 }
617 #[test]
618 fn test_libssl_dev_zypper() {
619 assert_eq!(
620 map_package_name("libssl-dev", PackageManager::Zypper),
621 "libopenssl-devel"
622 );
623 }
624 #[test]
625 fn test_libffi_dev_dnf() {
626 assert_eq!(
627 map_package_name("libffi-dev", PackageManager::Dnf),
628 "libffi-devel"
629 );
630 }
631 #[test]
632 fn test_zlib1g_dev_pacman() {
633 assert_eq!(
634 map_package_name("zlib1g-dev", PackageManager::Pacman),
635 "zlib"
636 );
637 }
638 #[test]
639 fn test_zlib1g_dev_dnf() {
640 assert_eq!(
641 map_package_name("zlib1g-dev", PackageManager::Dnf),
642 "zlib-devel"
643 );
644 }
645
646 #[test]
649 fn test_mesa_utils_pacman() {
650 assert_eq!(
651 map_package_name("mesa-utils", PackageManager::Pacman),
652 "mesa-demos"
653 );
654 }
655 #[test]
656 fn test_mesa_utils_dnf() {
657 assert_eq!(
658 map_package_name("mesa-utils", PackageManager::Dnf),
659 "mesa-demos"
660 );
661 }
662 #[test]
663 fn test_mesa_utils_zypper() {
664 assert_eq!(
665 map_package_name("mesa-utils", PackageManager::Zypper),
666 "Mesa-demo"
667 );
668 }
669 #[test]
670 fn test_libnuma_dev_pacman() {
671 assert_eq!(
672 map_package_name("libnuma-dev", PackageManager::Pacman),
673 "numactl"
674 );
675 }
676 #[test]
677 fn test_libnuma_dev_dnf() {
678 assert_eq!(
679 map_package_name("libnuma-dev", PackageManager::Dnf),
680 "numactl-devel"
681 );
682 }
683
684 #[test]
687 fn test_gh_pacman() {
688 assert_eq!(map_package_name("gh", PackageManager::Pacman), "github-cli");
689 }
690
691 #[test]
694 fn test_gnupg_dnf() {
695 assert_eq!(map_package_name("gnupg", PackageManager::Dnf), "gnupg2");
696 }
697 #[test]
698 fn test_gnupg_zypper() {
699 assert_eq!(map_package_name("gnupg", PackageManager::Zypper), "gpg2");
700 }
701 #[test]
702 fn test_ssh_pacman() {
703 assert_eq!(map_package_name("ssh", PackageManager::Pacman), "openssh");
704 }
705 #[test]
706 fn test_ssh_dnf() {
707 assert_eq!(
708 map_package_name("ssh", PackageManager::Dnf),
709 "openssh-clients"
710 );
711 }
712
713 #[test]
716 fn test_libbz2_dev_pacman() {
717 assert_eq!(
718 map_package_name("libbz2-dev", PackageManager::Pacman),
719 "bzip2"
720 );
721 }
722 #[test]
723 fn test_libbz2_dev_dnf() {
724 assert_eq!(
725 map_package_name("libbz2-dev", PackageManager::Dnf),
726 "bzip2-devel"
727 );
728 }
729 #[test]
730 fn test_libsqlite3_dev_pacman() {
731 assert_eq!(
732 map_package_name("libsqlite3-dev", PackageManager::Pacman),
733 "sqlite"
734 );
735 }
736 #[test]
737 fn test_libsqlite3_dev_zypper() {
738 assert_eq!(
739 map_package_name("libsqlite3-dev", PackageManager::Zypper),
740 "sqlite3-devel"
741 );
742 }
743 #[test]
744 fn test_uuid_dev_pacman() {
745 assert_eq!(
746 map_package_name("uuid-dev", PackageManager::Pacman),
747 "util-linux"
748 );
749 }
750 #[test]
751 fn test_uuid_dev_dnf() {
752 assert_eq!(
753 map_package_name("uuid-dev", PackageManager::Dnf),
754 "libuuid-devel"
755 );
756 }
757
758 #[test]
761 fn test_unknown_package_returns_original() {
762 assert_eq!(
763 map_package_name("some-unknown-package", PackageManager::Apt),
764 "some-unknown-package"
765 );
766 assert_eq!(
767 map_package_name("some-unknown-package", PackageManager::Pacman),
768 "some-unknown-package"
769 );
770 }
771
772 #[test]
773 fn test_unknown_package_manager_returns_original() {
774 assert_eq!(
775 map_package_name("build-essential", PackageManager::Unknown),
776 "build-essential"
777 );
778 }
779
780 #[test]
783 fn test_map_package_names_batch() {
784 let names = vec!["build-essential", "cmake", "python3-dev"];
785 let mapped = map_package_names(&names, PackageManager::Pacman);
786 assert_eq!(mapped, vec!["base-devel", "cmake", "python"]);
787 }
788
789 #[test]
792 fn test_identity_mappings() {
793 for pkg in &[
795 "gcc", "make", "cmake", "git", "curl", "wget", "clang", "lld",
796 ] {
797 assert_eq!(map_package_name(pkg, PackageManager::Apt), *pkg);
798 assert_eq!(map_package_name(pkg, PackageManager::Pacman), *pkg);
799 }
800 }
801
802 #[test]
805 fn test_has_mapping_known() {
806 assert!(has_mapping("build-essential", PackageManager::Pacman));
807 }
808
809 #[test]
810 fn test_has_mapping_identity() {
811 assert!(has_mapping("gcc", PackageManager::Apt));
813 }
814
815 #[test]
816 fn test_has_mapping_unknown() {
817 assert!(!has_mapping("totally-fake-package", PackageManager::Apt));
818 }
819
820 #[test]
823 fn test_known_packages_contains_key_packages() {
824 let known = get_known_packages();
825 assert!(known.contains(&"build-essential"));
826 assert!(known.contains(&"python3-dev"));
827 assert!(known.contains(&"libopenmpi-dev"));
828 assert!(known.contains(&"git"));
829 assert!(known.contains(&"libssl-dev"));
830 assert!(known.contains(&"rocminfo"));
831 }
832}