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, Default)]
63pub enum OnnxInstallMethod {
64 #[default]
66 MigraphxWheel,
67 SourceBuild,
69 PrebuiltWheel,
71}
72
73#[derive(Debug, Clone)]
75pub struct OnnxRuntimeConfig {
76 pub python_bin: String,
78 pub dry_run: bool,
80 pub rocm_version: Option<String>,
82 pub rocm_release: Option<String>,
84 pub gpu_arch: Option<String>,
86 pub workdir: Option<PathBuf>,
88 pub eigen_path: Option<PathBuf>,
90 pub use_preinstalled_eigen: bool,
92 pub install_method: OnnxInstallMethod,
94}
95
96impl Default for OnnxRuntimeConfig {
97 fn default() -> Self {
98 Self {
99 python_bin: "python3".to_string(),
100 dry_run: false,
101 rocm_version: None,
102 rocm_release: None,
103 gpu_arch: None,
104 workdir: None,
105 eigen_path: None,
106 use_preinstalled_eigen: false,
107 install_method: OnnxInstallMethod::default(),
108 }
109 }
110}
111
112impl OnnxRuntimeConfig {
113 pub fn workdir(&self) -> PathBuf {
115 self.workdir
116 .clone()
117 .unwrap_or_else(|| std::env::temp_dir().join("onnxruntime-rocm"))
118 }
119
120 pub fn gpu_arch(&self) -> &str {
122 self.gpu_arch.as_deref().unwrap_or("gfx1100")
123 }
124
125 pub fn rocm_version(&self) -> &str {
127 self.rocm_version.as_deref().unwrap_or("7.2")
128 }
129
130 pub fn rocm_release(&self) -> &str {
132 self.rocm_release.as_deref().unwrap_or("7.2.4")
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
138pub struct ShellCommand {
139 pub program: String,
141 pub args: Vec<String>,
143 pub env: Vec<(String, String)>,
145 pub working_dir: Option<PathBuf>,
147}
148
149pub struct OnnxRuntimeInstaller {
151 config: OnnxRuntimeConfig,
152}
153
154impl OnnxRuntimeInstaller {
155 pub fn new(config: OnnxRuntimeConfig) -> Self {
157 Self { config }
158 }
159
160 pub fn with_defaults() -> Self {
162 Self::new(OnnxRuntimeConfig::default())
163 }
164
165 pub fn dependencies(&self) -> &[&str] {
173 &["rocm"]
174 }
175
176 pub fn format_rocm_version_for_ort(&self, rocm_version: &str) -> String {
184 let parts: Vec<&str> = rocm_version.split('.').collect();
185 let major: u32 = parts.first().and_then(|s| s.parse().ok()).unwrap_or(7);
186 let minor: u32 = parts.get(1).and_then(|s| s.parse().ok()).unwrap_or(2);
187 let patch: u32 = parts.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
188 format!("{:02}{:02}{:02}", major, minor, patch)
189 }
190
191 pub fn build_prebuilt_install_command(&self) -> ShellCommand {
200 ShellCommand {
201 program: self.config.python_bin.clone(),
202 args: vec![
203 "-m".to_string(),
204 "pip".to_string(),
205 "install".to_string(),
206 "--upgrade".to_string(),
207 "--prefer-binary".to_string(),
208 "onnxruntime-rocm".to_string(),
209 ],
210 env: vec![],
211 working_dir: None,
212 }
213 }
214
215 pub fn build_migraphx_wheel_url(&self) -> String {
226 let release = self.config.rocm_release();
227 let python_bin = &self.config.python_bin;
228 let py_ver = if python_bin.contains('.') {
230 let parts: Vec<&str> = python_bin.split('.').collect();
231 if parts.len() >= 2 {
232 format!("{}{}", parts[0], parts[1])
233 } else {
234 "312".to_string()
235 }
236 } else {
237 "312".to_string()
238 };
239
240 format!(
241 "https://repo.radeon.com/rocm/manylinux/rocm-rel-{release}/\
242 onnxruntime_migraphx-1.23.2-cp{py_ver}-cp{py_ver}-\
243 manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"
244 )
245 }
246
247 pub fn build_migraphx_install_command(&self) -> ShellCommand {
253 let url = self.build_migraphx_wheel_url();
254 ShellCommand {
255 program: self.config.python_bin.clone(),
256 args: vec![
257 "-m".to_string(),
258 "pip".to_string(),
259 "install".to_string(),
260 "--upgrade".to_string(),
261 url,
262 ],
263 env: vec![],
264 working_dir: None,
265 }
266 }
267
268 pub fn build_model_optimizer_command(&self, model_path: &str) -> ShellCommand {
278 let optimized_path = format!("{}.optimized", model_path);
279
280 let script = format!(
281 "import onnxruntime as ort; \
282 opts = ort.SessionOptions(); \
283 opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL; \
284 opts.optimized_model_filepath = '{optimized_path}'; \
285 ort.InferenceSession('{model_path}', opts, providers=['CPUExecutionProvider']); \
286 print('Optimized: {model_path} -> {optimized_path}')"
287 );
288
289 ShellCommand {
290 program: self.config.python_bin.clone(),
291 args: vec!["-c".to_string(), script],
292 env: vec![],
293 working_dir: None,
294 }
295 }
296
297 pub fn build_git_clone_command(&self) -> ShellCommand {
306 ShellCommand {
307 program: "git".to_string(),
308 args: vec![
309 "clone".to_string(),
310 "--recursive".to_string(),
311 "https://github.com/microsoft/onnxruntime.git".to_string(),
312 ],
313 env: vec![],
314 working_dir: Some(self.config.workdir()),
315 }
316 }
317
318 pub fn build_git_checkout_command(&self) -> ShellCommand {
322 ShellCommand {
323 program: "git".to_string(),
324 args: vec!["checkout".to_string(), "v1.20.1".to_string()],
325 env: vec![],
326 working_dir: Some(self.config.workdir().join("onnxruntime")),
327 }
328 }
329
330 pub fn build_git_submodule_command(&self) -> ShellCommand {
332 ShellCommand {
333 program: "git".to_string(),
334 args: vec![
335 "submodule".to_string(),
336 "update".to_string(),
337 "--init".to_string(),
338 "--recursive".to_string(),
339 ],
340 env: vec![],
341 working_dir: Some(self.config.workdir().join("onnxruntime")),
342 }
343 }
344
345 pub fn build_build_command(&self, rocm_env: &RocmEnv) -> ShellCommand {
362 let rocm_path = rocm_env
363 .path()
364 .map(|p| p.to_string_lossy().to_string())
365 .unwrap_or_else(|| "/opt/rocm".to_string());
366
367 let rocm_version = self.config.rocm_version();
368 let ort_rocm_version = self.format_rocm_version_for_ort(rocm_version);
369 let hip_archs = HipArchs::from_gpu_arch(self.config.gpu_arch());
370 let nproc = std::thread::available_parallelism()
371 .map(|n| n.get().saturating_sub(1))
372 .unwrap_or(3);
373
374 let mut args = vec![
375 "--config".to_string(),
376 "Release".to_string(),
377 "--build_wheel".to_string(),
378 "--parallel".to_string(),
379 nproc.to_string(),
380 "--use_rocm".to_string(),
381 "--rocm_home".to_string(),
382 rocm_path.clone(),
383 "--rocm_version".to_string(),
384 ort_rocm_version,
385 "--use_migraphx".to_string(),
386 "--migraphx_home".to_string(),
387 rocm_path.clone(),
388 ];
389
390 if self.config.use_preinstalled_eigen {
391 if let Some(ref eigen_path) = self.config.eigen_path {
392 args.push("--use_preinstalled_eigen".to_string());
393 args.push("--eigen_path".to_string());
394 args.push(eigen_path.to_string_lossy().to_string());
395 }
396 }
397
398 let cmake_extra_defines = vec![
400 format!(
401 "CMAKE_HIP_ARCHITECTURES={}",
402 hip_archs.cmake_hip_architectures()
403 ),
404 "CMAKE_CXX_STANDARD=20".to_string(),
405 "onnxruntime_USE_EXTERNAL_ABSEIL=OFF".to_string(),
406 "CMAKE_DISABLE_FIND_PACKAGE_re2=ON".to_string(),
407 "CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON".to_string(),
408 "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=ON".to_string(),
409 "CMAKE_FIND_USE_PACKAGE_REGISTRY=OFF".to_string(),
410 "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF".to_string(),
411 format!("CMAKE_PREFIX_PATH={}", rocm_path),
412 "re2_DIR=RE2_DIR-NOTFOUND".to_string(),
413 "CMAKE_POLICY_VERSION_MINIMUM=3.5".to_string(),
414 ];
415
416 for define in cmake_extra_defines {
417 args.push("--cmake_extra_defines".to_string());
418 args.push(define);
419 }
420
421 if self.config.use_preinstalled_eigen {
422 if let Some(ref eigen_path) = self.config.eigen_path {
423 args.push("--cmake_extra_defines".to_string());
424 args.push(format!(
425 "FETCHCONTENT_SOURCE_DIR_EIGEN={}",
426 eigen_path.to_string_lossy()
427 ));
428 args.push("--cmake_extra_defines".to_string());
429 args.push("FETCHCONTENT_TRY_FIND_PACKAGE_MODE=NEVER".to_string());
430 }
431 }
432
433 args.push("--allow_running_as_root".to_string());
434
435 let env = vec![
436 ("ROCM_HOME".to_string(), rocm_path.clone()),
437 ("ROCM_PATH".to_string(), rocm_path.clone()),
438 ("HIP_PATH".to_string(), rocm_path),
439 ("PYTHONPATH".to_string(), String::new()),
440 ("CMAKE_PREFIX_PATH".to_string(), "/opt/rocm".to_string()),
441 ("CMAKE_CXX_STANDARD".to_string(), "20".to_string()),
442 (
443 "CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY".to_string(),
444 "ON".to_string(),
445 ),
446 (
447 "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY".to_string(),
448 "ON".to_string(),
449 ),
450 (
451 "CMAKE_FIND_USE_PACKAGE_REGISTRY".to_string(),
452 "OFF".to_string(),
453 ),
454 (
455 "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY".to_string(),
456 "OFF".to_string(),
457 ),
458 ];
459
460 ShellCommand {
461 program: "./build.sh".to_string(),
462 args,
463 env,
464 working_dir: Some(self.config.workdir().join("onnxruntime")),
465 }
466 }
467
468 pub fn build_uninstall_command(&self) -> ShellCommand {
474 ShellCommand {
475 program: self.config.python_bin.clone(),
476 args: vec![
477 "-m".to_string(),
478 "pip".to_string(),
479 "uninstall".to_string(),
480 "-y".to_string(),
481 "onnxruntime".to_string(),
482 "onnxruntime-rocm".to_string(),
483 "onnxruntime-gpu".to_string(),
484 "onnxruntime-migraphx".to_string(),
485 ],
486 env: vec![],
487 working_dir: None,
488 }
489 }
490
491 pub fn build_wheel_install_command(&self) -> ShellCommand {
496 let wheel_path = self
497 .config
498 .workdir()
499 .join("onnxruntime")
500 .join("build/Linux/Release/dist/*.whl");
501
502 ShellCommand {
503 program: self.config.python_bin.clone(),
504 args: vec![
505 "-m".to_string(),
506 "pip".to_string(),
507 "install".to_string(),
508 wheel_path.to_string_lossy().to_string(),
509 ],
510 env: vec![],
511 working_dir: None,
512 }
513 }
514
515 pub fn check_build_output(
523 &self,
524 stdout: &str,
525 stderr: &str,
526 exit_code: i32,
527 ) -> Result<(), String> {
528 if exit_code != 0 {
529 let error_patterns = [
530 "CMake Error",
531 "error:",
532 "FAILED:",
533 "fatal error:",
534 "Build failed",
535 "ninja: build stopped",
536 "Could NOT find",
537 ];
538
539 let combined = format!("{}\n{}", stdout, stderr);
540 let detected_errors: Vec<&str> = error_patterns
541 .iter()
542 .filter(|p| combined.contains(*p))
543 .copied()
544 .collect();
545
546 if detected_errors.is_empty() {
547 return Err(format!(
548 "ONNX Runtime build failed with exit code {} (no specific error pattern detected)",
549 exit_code
550 ));
551 }
552
553 return Err(format!(
554 "ONNX Runtime build failed with exit code {}. Detected errors: {}",
555 exit_code,
556 detected_errors.join(", ")
557 ));
558 }
559
560 Ok(())
561 }
562}
563
564#[cfg(test)]
569mod tests {
570 use super::*;
571 use std::path::PathBuf;
572
573 #[test]
576 fn test_build_command_has_rocm_flags() {
577 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
578 rocm_version: Some("7.2.0".to_string()),
579 gpu_arch: Some("gfx1100".to_string()),
580 ..Default::default()
581 });
582 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
583 let cmd = installer.build_build_command(&rocm_env);
584
585 assert_eq!(cmd.program, "./build.sh");
586 assert!(cmd.args.contains(&"--use_rocm".to_string()));
587 assert!(cmd.args.contains(&"--rocm_home".to_string()));
588 assert!(cmd.args.iter().any(|a| a == "/opt/rocm"));
589 assert!(cmd.args.contains(&"--use_migraphx".to_string()));
590 assert!(cmd.args.contains(&"--build_wheel".to_string()));
591 assert!(cmd.args.contains(&"--allow_running_as_root".to_string()));
592 }
593
594 #[test]
595 fn test_build_command_has_rocm_version() {
596 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
597 rocm_version: Some("7.2.0".to_string()),
598 ..Default::default()
599 });
600 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
601 let cmd = installer.build_build_command(&rocm_env);
602
603 assert!(cmd.args.contains(&"--rocm_version".to_string()));
604 assert!(cmd.args.contains(&"070200".to_string()));
606 }
607
608 #[test]
609 fn test_build_command_has_hip_architectures() {
610 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
611 gpu_arch: Some("gfx1100".to_string()),
612 ..Default::default()
613 });
614 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
615 let cmd = installer.build_build_command(&rocm_env);
616
617 assert!(cmd
618 .args
619 .iter()
620 .any(|a| a.contains("CMAKE_HIP_ARCHITECTURES=gfx1100;gfx1101;gfx1102;gfx1103")));
621 }
622
623 #[test]
624 fn test_build_command_has_cmake_extra_defines() {
625 let installer = OnnxRuntimeInstaller::with_defaults();
626 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
627 let cmd = installer.build_build_command(&rocm_env);
628
629 assert!(cmd
630 .args
631 .iter()
632 .any(|a| a.contains("onnxruntime_USE_EXTERNAL_ABSEIL=OFF")));
633 assert!(cmd
634 .args
635 .iter()
636 .any(|a| a.contains("CMAKE_DISABLE_FIND_PACKAGE_re2=ON")));
637 assert!(cmd
638 .args
639 .iter()
640 .any(|a| a.contains("CMAKE_POLICY_VERSION_MINIMUM=3.5")));
641 }
642
643 #[test]
646 fn test_build_command_includes_cmake_cxx_standard_20() {
647 let installer = OnnxRuntimeInstaller::with_defaults();
648 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
649 let cmd = installer.build_build_command(&rocm_env);
650
651 assert!(
654 cmd.args.iter().any(|a| a.contains("CMAKE_CXX_STANDARD=20")),
655 "build command must include CMAKE_CXX_STANDARD=20 cmake extra define, got args: {:?}",
656 cmd.args
657 );
658 }
659
660 #[test]
661 fn test_build_command_cmake_cxx_standard_is_cmake_extra_define() {
662 let installer = OnnxRuntimeInstaller::with_defaults();
663 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
664 let cmd = installer.build_build_command(&rocm_env);
665
666 let define_idx = cmd
668 .args
669 .iter()
670 .position(|a| a.contains("CMAKE_CXX_STANDARD=20"));
671 assert!(
672 define_idx.is_some(),
673 "CMAKE_CXX_STANDARD=20 not found in args"
674 );
675
676 let idx = define_idx.unwrap();
677 assert!(
678 idx > 0 && cmd.args[idx - 1] == "--cmake_extra_defines",
679 "CMAKE_CXX_STANDARD=20 must be preceded by --cmake_extra_defines"
680 );
681 }
682
683 #[test]
684 fn test_build_command_cmake_cxx_standard_env_var() {
685 let installer = OnnxRuntimeInstaller::with_defaults();
686 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
687 let cmd = installer.build_build_command(&rocm_env);
688
689 assert!(
692 cmd.env
693 .iter()
694 .any(|(k, v)| k == "CMAKE_CXX_STANDARD" && v == "20"),
695 "build command env must include CMAKE_CXX_STANDARD=20, got env: {:?}",
696 cmd.env
697 );
698 }
699
700 #[test]
701 fn test_build_command_has_parallel_flag() {
702 let installer = OnnxRuntimeInstaller::with_defaults();
703 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
704 let cmd = installer.build_build_command(&rocm_env);
705
706 assert!(cmd.args.contains(&"--parallel".to_string()));
707 }
708
709 #[test]
710 fn test_build_command_env_vars() {
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
716 .env
717 .iter()
718 .any(|(k, v)| k == "ROCM_HOME" && v == "/opt/rocm"));
719 assert!(cmd
720 .env
721 .iter()
722 .any(|(k, v)| k == "ROCM_PATH" && v == "/opt/rocm"));
723 assert!(cmd
724 .env
725 .iter()
726 .any(|(k, v)| k == "HIP_PATH" && v == "/opt/rocm"));
727 assert!(cmd
728 .env
729 .iter()
730 .any(|(k, v)| k == "PYTHONPATH" && v.is_empty()));
731 }
732
733 #[test]
734 fn test_build_command_with_eigen() {
735 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
736 use_preinstalled_eigen: true,
737 eigen_path: Some(PathBuf::from("/usr/include/eigen3")),
738 ..Default::default()
739 });
740 let rocm_env = RocmEnv::from_known(Some(PathBuf::from("/opt/rocm")), "7.2.0".to_string());
741 let cmd = installer.build_build_command(&rocm_env);
742
743 assert!(cmd.args.contains(&"--use_preinstalled_eigen".to_string()));
744 assert!(cmd.args.iter().any(|a| a.contains("/usr/include/eigen3")));
745 assert!(cmd
746 .args
747 .iter()
748 .any(|a| a.contains("FETCHCONTENT_SOURCE_DIR_EIGEN")));
749 }
750
751 #[test]
754 fn test_wheel_install_command() {
755 let installer = OnnxRuntimeInstaller::with_defaults();
756 let cmd = installer.build_wheel_install_command();
757
758 assert_eq!(cmd.program, "python3");
759 assert!(cmd.args.contains(&"-m".to_string()));
760 assert!(cmd.args.contains(&"pip".to_string()));
761 assert!(cmd.args.contains(&"install".to_string()));
762 assert!(cmd
763 .args
764 .iter()
765 .any(|a| a.contains("build/Linux/Release/dist/*.whl")));
766 }
767
768 #[test]
769 fn test_uninstall_command() {
770 let installer = OnnxRuntimeInstaller::with_defaults();
771 let cmd = installer.build_uninstall_command();
772
773 assert!(cmd.args.contains(&"uninstall".to_string()));
774 assert!(cmd.args.contains(&"-y".to_string()));
775 assert!(cmd.args.contains(&"onnxruntime".to_string()));
776 assert!(cmd.args.contains(&"onnxruntime-rocm".to_string()));
777 assert!(cmd.args.contains(&"onnxruntime-gpu".to_string()));
778 assert!(cmd.args.contains(&"onnxruntime-migraphx".to_string()));
779 }
780
781 #[test]
784 fn test_prebuilt_install_command() {
785 let installer = OnnxRuntimeInstaller::with_defaults();
786 let cmd = installer.build_prebuilt_install_command();
787
788 assert_eq!(cmd.program, "python3");
789 assert!(cmd.args.contains(&"-m".to_string()));
790 assert!(cmd.args.contains(&"pip".to_string()));
791 assert!(cmd.args.contains(&"--upgrade".to_string()));
792 assert!(cmd.args.contains(&"--prefer-binary".to_string()));
793 assert!(cmd.args.contains(&"onnxruntime-rocm".to_string()));
794 }
795
796 #[test]
799 fn test_git_clone_command() {
800 let installer = OnnxRuntimeInstaller::with_defaults();
801 let cmd = installer.build_git_clone_command();
802 assert_eq!(cmd.program, "git");
803 assert!(cmd.args.contains(&"clone".to_string()));
804 assert!(cmd.args.contains(&"--recursive".to_string()));
805 assert!(cmd.args.iter().any(|a| a.contains("microsoft/onnxruntime")));
806 }
807
808 #[test]
809 fn test_git_checkout_command() {
810 let installer = OnnxRuntimeInstaller::with_defaults();
811 let cmd = installer.build_git_checkout_command();
812 assert!(cmd.args.contains(&"v1.20.1".to_string()));
813 }
814
815 #[test]
818 fn test_rocm_version_formatting() {
819 let installer = OnnxRuntimeInstaller::with_defaults();
820 assert_eq!(installer.format_rocm_version_for_ort("7.2.0"), "070200");
821 assert_eq!(installer.format_rocm_version_for_ort("7.0.0"), "070000");
822 assert_eq!(installer.format_rocm_version_for_ort("7.2.1"), "070201");
823 }
824
825 #[test]
828 fn test_hip_archs_gfx1030() {
829 let archs = HipArchs::from_gpu_arch("gfx1030");
830 assert_eq!(archs.cmake_hip_architectures(), "gfx1030");
831 }
832
833 #[test]
834 fn test_hip_archs_gfx1100() {
835 let archs = HipArchs::from_gpu_arch("gfx1100");
836 assert_eq!(
837 archs.cmake_hip_architectures(),
838 "gfx1100;gfx1101;gfx1102;gfx1103"
839 );
840 }
841
842 #[test]
843 fn test_hip_archs_gfx1200() {
844 let archs = HipArchs::from_gpu_arch("gfx1200");
845 assert_eq!(archs.cmake_hip_architectures(), "gfx1200;gfx1201");
846 }
847
848 #[test]
849 fn test_hip_archs_default() {
850 let archs = HipArchs::from_gpu_arch("gfx900");
851 assert_eq!(archs.cmake_hip_architectures(), "gfx1100");
852 }
853
854 #[test]
857 fn test_dependencies() {
858 let installer = OnnxRuntimeInstaller::with_defaults();
859 let deps = installer.dependencies();
860 assert!(deps.contains(&"rocm"));
861 }
862
863 #[test]
866 fn test_build_error_cmake() {
867 let installer = OnnxRuntimeInstaller::with_defaults();
868 let result = installer.check_build_output("", "CMake Error at cmake/CMakeLists.txt:42", 1);
869 assert!(result.is_err());
870 assert!(result.unwrap_err().contains("CMake Error"));
871 }
872
873 #[test]
874 fn test_build_error_ninja() {
875 let installer = OnnxRuntimeInstaller::with_defaults();
876 let result =
877 installer.check_build_output("ninja: build stopped: subcommand failed.", "", 1);
878 assert!(result.is_err());
879 assert!(result.unwrap_err().contains("ninja: build stopped"));
880 }
881
882 #[test]
883 fn test_build_error_success() {
884 let installer = OnnxRuntimeInstaller::with_defaults();
885 let result = installer.check_build_output("Build succeeded", "", 0);
886 assert!(result.is_ok());
887 }
888
889 #[test]
892 fn test_config_defaults() {
893 let config = OnnxRuntimeConfig::default();
894 assert_eq!(config.python_bin, "python3");
895 assert!(!config.dry_run);
896 assert!(config.rocm_version.is_none());
897 assert!(config.rocm_release.is_none());
898 assert!(config.gpu_arch.is_none());
899 assert!(config.workdir.is_none());
900 assert!(!config.use_preinstalled_eigen);
901 assert!(config.eigen_path.is_none());
902 assert_eq!(config.install_method, OnnxInstallMethod::MigraphxWheel);
903 }
904
905 #[test]
908 fn test_migraphx_wheel_url_default() {
909 let installer = OnnxRuntimeInstaller::with_defaults();
910 let url = installer.build_migraphx_wheel_url();
911 assert!(url.contains("repo.radeon.com/rocm/manylinux/rocm-rel-7.2.4/"));
912 assert!(url.contains("onnxruntime_migraphx-1.23.2"));
913 assert!(url.contains("manylinux_2_27_x86_64"));
914 }
915
916 #[test]
917 fn test_migraphx_wheel_url_custom_release() {
918 let installer = OnnxRuntimeInstaller::new(OnnxRuntimeConfig {
919 rocm_release: Some("7.2.1".to_string()),
920 ..Default::default()
921 });
922 let url = installer.build_migraphx_wheel_url();
923 assert!(url.contains("rocm-rel-7.2.1/"));
924 }
925
926 #[test]
927 fn test_migraphx_install_command() {
928 let installer = OnnxRuntimeInstaller::with_defaults();
929 let cmd = installer.build_migraphx_install_command();
930 assert_eq!(cmd.program, "python3");
931 assert!(cmd.args.contains(&"-m".to_string()));
932 assert!(cmd.args.contains(&"pip".to_string()));
933 assert!(cmd.args.contains(&"install".to_string()));
934 assert!(cmd.args.iter().any(|a| a.contains("repo.radeon.com")));
935 assert!(cmd.args.iter().any(|a| a.contains("onnxruntime_migraphx")));
936 }
937
938 #[test]
941 fn test_model_optimizer_command() {
942 let installer = OnnxRuntimeInstaller::with_defaults();
943 let cmd = installer.build_model_optimizer_command("/path/to/model.onnx");
944 assert_eq!(cmd.program, "python3");
945 assert!(cmd.args.contains(&"-c".to_string()));
946 let script = &cmd.args[1];
947 assert!(script.contains("ORT_ENABLE_ALL"));
948 assert!(script.contains("/path/to/model.onnx"));
949 assert!(script.contains("/path/to/model.onnx.optimized"));
950 }
951
952 #[test]
955 fn test_install_method_default() {
956 assert_eq!(
957 OnnxInstallMethod::default(),
958 OnnxInstallMethod::MigraphxWheel
959 );
960 }
961}