1use crate::installers::common::RocmEnv;
17use std::path::PathBuf;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum HipArchs {
26 Gfx1030,
28 Gfx1100,
30 Gfx1200,
32 Default,
34}
35
36impl HipArchs {
37 pub fn from_gpu_arch(gpu_arch: &str) -> Self {
39 if gpu_arch.starts_with("gfx103") {
40 HipArchs::Gfx1030
41 } else if gpu_arch.starts_with("gfx110") {
42 HipArchs::Gfx1100
43 } else if gpu_arch.starts_with("gfx120") {
44 HipArchs::Gfx1200
45 } else {
46 HipArchs::Default
47 }
48 }
49
50 pub fn cmake_hip_architectures(&self) -> &str {
52 match self {
53 HipArchs::Gfx1030 => "gfx1030",
54 HipArchs::Gfx1100 => "gfx1100;gfx1101;gfx1102;gfx1103",
55 HipArchs::Gfx1200 => "gfx1200;gfx1201",
56 HipArchs::Default => "gfx1100",
57 }
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum OnnxInstallMethod {
64 MigraphxWheel,
66 SourceBuild,
68 PrebuiltWheel,
70}
71
72impl Default for OnnxInstallMethod {
73 fn default() -> Self {
74 OnnxInstallMethod::MigraphxWheel
75 }
76}
77
78#[derive(Debug, Clone)]
80pub struct OnnxRuntimeConfig {
81 pub python_bin: String,
83 pub dry_run: bool,
85 pub rocm_version: Option<String>,
87 pub rocm_release: Option<String>,
89 pub gpu_arch: Option<String>,
91 pub workdir: Option<PathBuf>,
93 pub eigen_path: Option<PathBuf>,
95 pub use_preinstalled_eigen: bool,
97 pub install_method: OnnxInstallMethod,
99}
100
101impl Default for OnnxRuntimeConfig {
102 fn default() -> Self {
103 Self {
104 python_bin: "python3".to_string(),
105 dry_run: false,
106 rocm_version: None,
107 rocm_release: None,
108 gpu_arch: None,
109 workdir: None,
110 eigen_path: None,
111 use_preinstalled_eigen: false,
112 install_method: OnnxInstallMethod::default(),
113 }
114 }
115}
116
117impl OnnxRuntimeConfig {
118 pub fn workdir(&self) -> PathBuf {
120 self.workdir
121 .clone()
122 .unwrap_or_else(|| std::env::temp_dir().join("onnxruntime-rocm"))
123 }
124
125 pub fn gpu_arch(&self) -> &str {
127 self.gpu_arch.as_deref().unwrap_or("gfx1100")
128 }
129
130 pub fn rocm_version(&self) -> &str {
132 self.rocm_version.as_deref().unwrap_or("7.2")
133 }
134
135 pub fn rocm_release(&self) -> &str {
137 self.rocm_release.as_deref().unwrap_or("7.2.4")
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct ShellCommand {
144 pub program: String,
146 pub args: Vec<String>,
148 pub env: Vec<(String, String)>,
150 pub working_dir: Option<PathBuf>,
152}
153
154pub struct OnnxRuntimeInstaller {
156 config: OnnxRuntimeConfig,
157}
158
159impl OnnxRuntimeInstaller {
160 pub fn new(config: OnnxRuntimeConfig) -> Self {
162 Self { config }
163 }
164
165 pub fn with_defaults() -> Self {
167 Self::new(OnnxRuntimeConfig::default())
168 }
169
170 pub fn dependencies(&self) -> &[&str] {
178 &["rocm"]
179 }
180
181 pub fn format_rocm_version_for_ort(&self, rocm_version: &str) -> String {
189 let parts: Vec<&str> = rocm_version.split('.').collect();
190 let major: u32 = parts.first().and_then(|s| s.parse().ok()).unwrap_or(7);
191 let minor: u32 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(2);
192 let patch: u32 = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
193 format!("{:02}{:02}{:02}", major, minor, patch)
194 }
195
196 pub fn build_prebuilt_install_command(&self) -> ShellCommand {
205 ShellCommand {
206 program: self.config.python_bin.clone(),
207 args: vec![
208 "-m".to_string(),
209 "pip".to_string(),
210 "install".to_string(),
211 "--upgrade".to_string(),
212 "--prefer-binary".to_string(),
213 "onnxruntime-rocm".to_string(),
214 ],
215 env: vec![],
216 working_dir: None,
217 }
218 }
219
220 pub fn build_migraphx_wheel_url(&self) -> String {
231 let release = self.config.rocm_release();
232 let python_bin = &self.config.python_bin;
233 let py_ver = if python_bin.contains('.') {
235 let parts: Vec<&str> = python_bin.split('.').collect();
236 if parts.len() >= 2 {
237 format!("{}{}", parts[0], parts[1])
238 } else {
239 "312".to_string()
240 }
241 } else {
242 "312".to_string()
243 };
244
245 format!(
246 "https://repo.radeon.com/rocm/manylinux/rocm-rel-{release}/\
247 onnxruntime_migraphx-1.23.2-cp{py_ver}-cp{py_ver}-\
248 manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"
249 )
250 }
251
252 pub fn build_migraphx_install_command(&self) -> ShellCommand {
258 let url = self.build_migraphx_wheel_url();
259 ShellCommand {
260 program: self.config.python_bin.clone(),
261 args: vec![
262 "-m".to_string(),
263 "pip".to_string(),
264 "install".to_string(),
265 "--upgrade".to_string(),
266 url,
267 ],
268 env: vec![],
269 working_dir: None,
270 }
271 }
272
273 pub fn build_model_optimizer_command(&self, model_path: &str) -> ShellCommand {
283 let optimized_path = if model_path.ends_with(".onnx") {
284 format!("{}.optimized", model_path)
285 } else {
286 format!("{}.optimized", model_path)
287 };
288
289 let script = format!(
290 "import onnxruntime as ort; \
291 opts = ort.SessionOptions(); \
292 opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL; \
293 opts.optimized_model_filepath = '{optimized_path}'; \
294 ort.InferenceSession('{model_path}', opts, providers=['CPUExecutionProvider']); \
295 print('Optimized: {model_path} -> {optimized_path}')"
296 );
297
298 ShellCommand {
299 program: self.config.python_bin.clone(),
300 args: vec!["-c".to_string(), script],
301 env: vec![],
302 working_dir: None,
303 }
304 }
305
306 pub fn build_git_clone_command(&self) -> ShellCommand {
315 ShellCommand {
316 program: "git".to_string(),
317 args: vec![
318 "clone".to_string(),
319 "--recursive".to_string(),
320 "https://github.com/microsoft/onnxruntime.git".to_string(),
321 ],
322 env: vec![],
323 working_dir: Some(self.config.workdir()),
324 }
325 }
326
327 pub fn build_git_checkout_command(&self) -> ShellCommand {
331 ShellCommand {
332 program: "git".to_string(),
333 args: vec!["checkout".to_string(), "v1.20.1".to_string()],
334 env: vec![],
335 working_dir: Some(self.config.workdir().join("onnxruntime")),
336 }
337 }
338
339 pub fn build_git_submodule_command(&self) -> ShellCommand {
341 ShellCommand {
342 program: "git".to_string(),
343 args: vec![
344 "submodule".to_string(),
345 "update".to_string(),
346 "--init".to_string(),
347 "--recursive".to_string(),
348 ],
349 env: vec![],
350 working_dir: Some(self.config.workdir().join("onnxruntime")),
351 }
352 }
353
354 pub fn build_build_command(&self, rocm_env: &RocmEnv) -> ShellCommand {
371 let rocm_path = rocm_env
372 .path()
373 .map(|p| p.to_string_lossy().to_string())
374 .unwrap_or_else(|| "/opt/rocm".to_string());
375
376 let rocm_version = self.config.rocm_version();
377 let ort_rocm_version = self.format_rocm_version_for_ort(rocm_version);
378 let hip_archs = HipArchs::from_gpu_arch(self.config.gpu_arch());
379 let nproc = std::thread::available_parallelism()
380 .map(|n| n.get().saturating_sub(1))
381 .unwrap_or(3);
382
383 let mut args = vec![
384 "--config".to_string(),
385 "Release".to_string(),
386 "--build_wheel".to_string(),
387 "--parallel".to_string(),
388 nproc.to_string(),
389 "--use_rocm".to_string(),
390 "--rocm_home".to_string(),
391 rocm_path.clone(),
392 "--rocm_version".to_string(),
393 ort_rocm_version,
394 "--use_migraphx".to_string(),
395 "--migraphx_home".to_string(),
396 rocm_path.clone(),
397 ];
398
399 if self.config.use_preinstalled_eigen {
400 if let Some(ref eigen_path) = self.config.eigen_path {
401 args.push("--use_preinstalled_eigen".to_string());
402 args.push("--eigen_path".to_string());
403 args.push(eigen_path.to_string_lossy().to_string());
404 }
405 }
406
407 let cmake_extra_defines = vec![
409 format!(
410 "CMAKE_HIP_ARCHITECTURES={}",
411 hip_archs.cmake_hip_architectures()
412 ),
413 "CMAKE_CXX_STANDARD=20".to_string(),
414 "onnxruntime_USE_EXTERNAL_ABSEIL=OFF".to_string(),
415 "CMAKE_DISABLE_FIND_PACKAGE_re2=ON".to_string(),
416 "CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON".to_string(),
417 "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=ON".to_string(),
418 "CMAKE_FIND_USE_PACKAGE_REGISTRY=OFF".to_string(),
419 "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF".to_string(),
420 format!("CMAKE_PREFIX_PATH={}", rocm_path),
421 "re2_DIR=RE2_DIR-NOTFOUND".to_string(),
422 "CMAKE_POLICY_VERSION_MINIMUM=3.5".to_string(),
423 ];
424
425 for define in cmake_extra_defines {
426 args.push("--cmake_extra_defines".to_string());
427 args.push(define);
428 }
429
430 if self.config.use_preinstalled_eigen {
431 if let Some(ref eigen_path) = self.config.eigen_path {
432 args.push("--cmake_extra_defines".to_string());
433 args.push(format!(
434 "FETCHCONTENT_SOURCE_DIR_EIGEN={}",
435 eigen_path.to_string_lossy()
436 ));
437 args.push("--cmake_extra_defines".to_string());
438 args.push("FETCHCONTENT_TRY_FIND_PACKAGE_MODE=NEVER".to_string());
439 }
440 }
441
442 args.push("--allow_running_as_root".to_string());
443
444 let env = vec![
445 ("ROCM_HOME".to_string(), rocm_path.clone()),
446 ("ROCM_PATH".to_string(), rocm_path.clone()),
447 ("HIP_PATH".to_string(), rocm_path),
448 ("PYTHONPATH".to_string(), String::new()),
449 ("CMAKE_PREFIX_PATH".to_string(), "/opt/rocm".to_string()),
450 ("CMAKE_CXX_STANDARD".to_string(), "20".to_string()),
451 (
452 "CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY".to_string(),
453 "ON".to_string(),
454 ),
455 (
456 "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY".to_string(),
457 "ON".to_string(),
458 ),
459 (
460 "CMAKE_FIND_USE_PACKAGE_REGISTRY".to_string(),
461 "OFF".to_string(),
462 ),
463 (
464 "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY".to_string(),
465 "OFF".to_string(),
466 ),
467 ];
468
469 ShellCommand {
470 program: "./build.sh".to_string(),
471 args,
472 env,
473 working_dir: Some(self.config.workdir().join("onnxruntime")),
474 }
475 }
476
477 pub fn build_uninstall_command(&self) -> ShellCommand {
483 ShellCommand {
484 program: self.config.python_bin.clone(),
485 args: vec![
486 "-m".to_string(),
487 "pip".to_string(),
488 "uninstall".to_string(),
489 "-y".to_string(),
490 "onnxruntime".to_string(),
491 "onnxruntime-rocm".to_string(),
492 "onnxruntime-gpu".to_string(),
493 "onnxruntime-migraphx".to_string(),
494 ],
495 env: vec![],
496 working_dir: None,
497 }
498 }
499
500 pub fn build_wheel_install_command(&self) -> ShellCommand {
505 let wheel_path = self
506 .config
507 .workdir()
508 .join("onnxruntime")
509 .join("build/Linux/Release/dist/*.whl");
510
511 ShellCommand {
512 program: self.config.python_bin.clone(),
513 args: vec![
514 "-m".to_string(),
515 "pip".to_string(),
516 "install".to_string(),
517 wheel_path.to_string_lossy().to_string(),
518 ],
519 env: vec![],
520 working_dir: None,
521 }
522 }
523
524 pub fn check_build_output(
532 &self,
533 stdout: &str,
534 stderr: &str,
535 exit_code: i32,
536 ) -> Result<(), String> {
537 if exit_code != 0 {
538 let error_patterns = [
539 "CMake Error",
540 "error:",
541 "FAILED:",
542 "fatal error:",
543 "Build failed",
544 "ninja: build stopped",
545 "Could NOT find",
546 ];
547
548 let combined = format!("{}\n{}", stdout, stderr);
549 let detected_errors: Vec<&str> = error_patterns
550 .iter()
551 .filter(|p| combined.contains(*p))
552 .copied()
553 .collect();
554
555 if detected_errors.is_empty() {
556 return Err(format!(
557 "ONNX Runtime build failed with exit code {} (no specific error pattern detected)",
558 exit_code
559 ));
560 }
561
562 return Err(format!(
563 "ONNX Runtime build failed with exit code {}. Detected errors: {}",
564 exit_code,
565 detected_errors.join(", ")
566 ));
567 }
568
569 Ok(())
570 }
571}
572
573#[cfg(test)]
578mod tests {
579 use super::*;
580 use std::path::PathBuf;
581
582 #[test]
585 fn test_build_command_has_rocm_flags() {
586 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
587 rocm_version: Some("7.2.0".to_string()),
588 gpu_arch: Some("gfx1100".to_string()),
589 ..Default::default()
590 });
591 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
592 let cmd = installer.build_build_command(&rocm_env);
593
594 assert_eq!(cmd.program, "./build.sh");
595 assert!(cmd.args.contains(&"--use_rocm".to_string()));
596 assert!(cmd.args.contains(&"--rocm_home".to_string()));
597 assert!(cmd.args.iter().any(|a| a == "/opt/rocm"));
598 assert!(cmd.args.contains(&"--use_migraphx".to_string()));
599 assert!(cmd.args.contains(&"--build_wheel".to_string()));
600 assert!(cmd.args.contains(&"--allow_running_as_root".to_string()));
601 }
602
603 #[test]
604 fn test_build_command_has_rocm_version() {
605 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
606 rocm_version: Some("7.2.0".to_string()),
607 ..Default::default()
608 });
609 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
610 let cmd = installer.build_build_command(&rocm_env);
611
612 assert!(cmd.args.contains(&"--rocm_version".to_string()));
613 assert!(cmd.args.contains(&"070200".to_string()));
615 }
616
617 #[test]
618 fn test_build_command_has_hip_architectures() {
619 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
620 gpu_arch: Some("gfx1100".to_string()),
621 ..Default::default()
622 });
623 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
624 let cmd = installer.build_build_command(&rocm_env);
625
626 assert!(cmd
627 .args
628 .iter()
629 .any(|a| a.contains("CMAKE_HIP_ARCHITECTURES=gfx1100;gfx1101;gfx1102;gfx1103")));
630 }
631
632 #[test]
633 fn test_build_command_has_cmake_extra_defines() {
634 let installer = OnnxRuntimeInstaller::with_defaults();
635 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
636 let cmd = installer.build_build_command(&rocm_env);
637
638 assert!(cmd
639 .args
640 .iter()
641 .any(|a| a.contains("onnxruntime_USE_EXTERNAL_ABSEIL=OFF")));
642 assert!(cmd
643 .args
644 .iter()
645 .any(|a| a.contains("CMAKE_DISABLE_FIND_PACKAGE_re2=ON")));
646 assert!(cmd
647 .args
648 .iter()
649 .any(|a| a.contains("CMAKE_POLICY_VERSION_MINIMUM=3.5")));
650 }
651
652 #[test]
655 fn test_build_command_includes_cmake_cxx_standard_20() {
656 let installer = OnnxRuntimeInstaller::with_defaults();
657 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
658 let cmd = installer.build_build_command(&rocm_env);
659
660 assert!(
663 cmd.args.iter().any(|a| a.contains("CMAKE_CXX_STANDARD=20")),
664 "build command must include CMAKE_CXX_STANDARD=20 cmake extra define, got args: {:?}",
665 cmd.args
666 );
667 }
668
669 #[test]
670 fn test_build_command_cmake_cxx_standard_is_cmake_extra_define() {
671 let installer = OnnxRuntimeInstaller::with_defaults();
672 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
673 let cmd = installer.build_build_command(&rocm_env);
674
675 let define_idx = cmd
677 .args
678 .iter()
679 .position(|a| a.contains("CMAKE_CXX_STANDARD=20"));
680 assert!(
681 define_idx.is_some(),
682 "CMAKE_CXX_STANDARD=20 not found in args"
683 );
684
685 let idx = define_idx.unwrap();
686 assert!(
687 idx > 0 && cmd.args[idx - 1] == "--cmake_extra_defines",
688 "CMAKE_CXX_STANDARD=20 must be preceded by --cmake_extra_defines"
689 );
690 }
691
692 #[test]
693 fn test_build_command_cmake_cxx_standard_env_var() {
694 let installer = OnnxRuntimeInstaller::with_defaults();
695 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
696 let cmd = installer.build_build_command(&rocm_env);
697
698 assert!(
701 cmd.env
702 .iter()
703 .any(|(k, v)| k == "CMAKE_CXX_STANDARD" && v == "20"),
704 "build command env must include CMAKE_CXX_STANDARD=20, got env: {:?}",
705 cmd.env
706 );
707 }
708
709 #[test]
710 fn test_build_command_has_parallel_flag() {
711 let installer = OnnxRuntimeInstaller::with_defaults();
712 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
713 let cmd = installer.build_build_command(&rocm_env);
714
715 assert!(cmd.args.contains(&"--parallel".to_string()));
716 }
717
718 #[test]
719 fn test_build_command_env_vars() {
720 let installer = OnnxRuntimeInstaller::with_defaults();
721 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
722 let cmd = installer.build_build_command(&rocm_env);
723
724 assert!(cmd
725 .env
726 .iter()
727 .any(|(k, v)| k == "ROCM_HOME" && v == "/opt/rocm"));
728 assert!(cmd
729 .env
730 .iter()
731 .any(|(k, v)| k == "ROCM_PATH" && v == "/opt/rocm"));
732 assert!(cmd
733 .env
734 .iter()
735 .any(|(k, v)| k == "HIP_PATH" && v == "/opt/rocm"));
736 assert!(cmd
737 .env
738 .iter()
739 .any(|(k, v)| k == "PYTHONPATH" && v.is_empty()));
740 }
741
742 #[test]
743 fn test_build_command_with_eigen() {
744 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
745 use_preinstalled_eigen: true,
746 eigen_path: Some(PathBuf::from("/usr/include/eigen3")),
747 ..Default::default()
748 });
749 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
750 let cmd = installer.build_build_command(&rocm_env);
751
752 assert!(cmd.args.contains(&"--use_preinstalled_eigen".to_string()));
753 assert!(cmd.args.iter().any(|a| a.contains("/usr/include/eigen3")));
754 assert!(cmd
755 .args
756 .iter()
757 .any(|a| a.contains("FETCHCONTENT_SOURCE_DIR_EIGEN")));
758 }
759
760 #[test]
763 fn test_wheel_install_command() {
764 let installer = OnnxRuntimeInstaller::with_defaults();
765 let cmd = installer.build_wheel_install_command();
766
767 assert_eq!(cmd.program, "python3");
768 assert!(cmd.args.contains(&"-m".to_string()));
769 assert!(cmd.args.contains(&"pip".to_string()));
770 assert!(cmd.args.contains(&"install".to_string()));
771 assert!(cmd
772 .args
773 .iter()
774 .any(|a| a.contains("build/Linux/Release/dist/*.whl")));
775 }
776
777 #[test]
778 fn test_uninstall_command() {
779 let installer = OnnxRuntimeInstaller::with_defaults();
780 let cmd = installer.build_uninstall_command();
781
782 assert!(cmd.args.contains(&"uninstall".to_string()));
783 assert!(cmd.args.contains(&"-y".to_string()));
784 assert!(cmd.args.contains(&"onnxruntime".to_string()));
785 assert!(cmd.args.contains(&"onnxruntime-rocm".to_string()));
786 assert!(cmd.args.contains(&"onnxruntime-gpu".to_string()));
787 assert!(cmd.args.contains(&"onnxruntime-migraphx".to_string()));
788 }
789
790 #[test]
793 fn test_prebuilt_install_command() {
794 let installer = OnnxRuntimeInstaller::with_defaults();
795 let cmd = installer.build_prebuilt_install_command();
796
797 assert_eq!(cmd.program, "python3");
798 assert!(cmd.args.contains(&"-m".to_string()));
799 assert!(cmd.args.contains(&"pip".to_string()));
800 assert!(cmd.args.contains(&"--upgrade".to_string()));
801 assert!(cmd.args.contains(&"--prefer-binary".to_string()));
802 assert!(cmd.args.contains(&"onnxruntime-rocm".to_string()));
803 }
804
805 #[test]
808 fn test_git_clone_command() {
809 let installer = OnnxRuntimeInstaller::with_defaults();
810 let cmd = installer.build_git_clone_command();
811 assert_eq!(cmd.program, "git");
812 assert!(cmd.args.contains(&"clone".to_string()));
813 assert!(cmd.args.contains(&"--recursive".to_string()));
814 assert!(cmd.args.iter().any(|a| a.contains("microsoft/onnxruntime")));
815 }
816
817 #[test]
818 fn test_git_checkout_command() {
819 let installer = OnnxRuntimeInstaller::with_defaults();
820 let cmd = installer.build_git_checkout_command();
821 assert!(cmd.args.contains(&"v1.20.1".to_string()));
822 }
823
824 #[test]
827 fn test_rocm_version_formatting() {
828 let installer = OnnxRuntimeInstaller::with_defaults();
829 assert_eq!(installer.format_rocm_version_for_ort("7.2.0"), "070200");
830 assert_eq!(installer.format_rocm_version_for_ort("7.0.0"), "070000");
831 assert_eq!(installer.format_rocm_version_for_ort("7.2.1"), "070201");
832 }
833
834 #[test]
837 fn test_hip_archs_gfx1030() {
838 let archs = HipArchs::from_gpu_arch("gfx1030");
839 assert_eq!(archs.cmake_hip_architectures(), "gfx1030");
840 }
841
842 #[test]
843 fn test_hip_archs_gfx1100() {
844 let archs = HipArchs::from_gpu_arch("gfx1100");
845 assert_eq!(
846 archs.cmake_hip_architectures(),
847 "gfx1100;gfx1101;gfx1102;gfx1103"
848 );
849 }
850
851 #[test]
852 fn test_hip_archs_gfx1200() {
853 let archs = HipArchs::from_gpu_arch("gfx1200");
854 assert_eq!(archs.cmake_hip_architectures(), "gfx1200;gfx1201");
855 }
856
857 #[test]
858 fn test_hip_archs_default() {
859 let archs = HipArchs::from_gpu_arch("gfx900");
860 assert_eq!(archs.cmake_hip_architectures(), "gfx1100");
861 }
862
863 #[test]
866 fn test_dependencies() {
867 let installer = OnnxRuntimeInstaller::with_defaults();
868 let deps = installer.dependencies();
869 assert!(deps.contains(&"rocm"));
870 }
871
872 #[test]
875 fn test_build_error_cmake() {
876 let installer = OnnxRuntimeInstaller::with_defaults();
877 let result = installer.check_build_output("", "CMake Error at cmake/CMakeLists.txt:42", 1);
878 assert!(result.is_err());
879 assert!(result.unwrap_err().contains("CMake Error"));
880 }
881
882 #[test]
883 fn test_build_error_ninja() {
884 let installer = OnnxRuntimeInstaller::with_defaults();
885 let result =
886 installer.check_build_output("ninja: build stopped: subcommand failed.", "", 1);
887 assert!(result.is_err());
888 assert!(result.unwrap_err().contains("ninja: build stopped"));
889 }
890
891 #[test]
892 fn test_build_error_success() {
893 let installer = OnnxRuntimeInstaller::with_defaults();
894 let result = installer.check_build_output("Build succeeded", "", 0);
895 assert!(result.is_ok());
896 }
897
898 #[test]
901 fn test_config_defaults() {
902 let config = OnnxRuntimeConfig::default();
903 assert_eq!(config.python_bin, "python3");
904 assert!(!config.dry_run);
905 assert!(config.rocm_version.is_none());
906 assert!(config.rocm_release.is_none());
907 assert!(config.gpu_arch.is_none());
908 assert!(config.workdir.is_none());
909 assert!(!config.use_preinstalled_eigen);
910 assert!(config.eigen_path.is_none());
911 assert_eq!(config.install_method, OnnxInstallMethod::MigraphxWheel);
912 }
913
914 #[test]
917 fn test_migraphx_wheel_url_default() {
918 let installer = OnnxRuntimeInstaller::with_defaults();
919 let url = installer.build_migraphx_wheel_url();
920 assert!(url.contains("repo.radeon.com/rocm/manylinux/rocm-rel-7.2.4/"));
921 assert!(url.contains("onnxruntime_migraphx-1.23.2"));
922 assert!(url.contains("manylinux_2_27_x86_64"));
923 }
924
925 #[test]
926 fn test_migraphx_wheel_url_custom_release() {
927 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
928 rocm_release: Some("7.2.1".to_string()),
929 ..Default::default()
930 });
931 let url = installer.build_migraphx_wheel_url();
932 assert!(url.contains("rocm-rel-7.2.1/"));
933 }
934
935 #[test]
936 fn test_migraphx_install_command() {
937 let installer = OnnxRuntimeInstaller::with_defaults();
938 let cmd = installer.build_migraphx_install_command();
939 assert_eq!(cmd.program, "python3");
940 assert!(cmd.args.contains(&"-m".to_string()));
941 assert!(cmd.args.contains(&"pip".to_string()));
942 assert!(cmd.args.contains(&"install".to_string()));
943 assert!(cmd.args.iter().any(|a| a.contains("repo.radeon.com")));
944 assert!(cmd.args.iter().any(|a| a.contains("onnxruntime_migraphx")));
945 }
946
947 #[test]
950 fn test_model_optimizer_command() {
951 let installer = OnnxRuntimeInstaller::with_defaults();
952 let cmd = installer.build_model_optimizer_command("/path/to/model.onnx");
953 assert_eq!(cmd.program, "python3");
954 assert!(cmd.args.contains(&"-c".to_string()));
955 let script = &cmd.args[1];
956 assert!(script.contains("ORT_ENABLE_ALL"));
957 assert!(script.contains("/path/to/model.onnx"));
958 assert!(script.contains("/path/to/model.onnx.optimized"));
959 }
960
961 #[test]
964 fn test_install_method_default() {
965 assert_eq!(
966 OnnxInstallMethod::default(),
967 OnnxInstallMethod::MigraphxWheel
968 );
969 }
970}