Skip to main content

alien_core/
build_targets.rs

1//! Cross-compilation build target types
2//!
3//! These types identify target OS/architecture combinations used by the open-source
4//! build system (alien-build) for cross-compilation.
5
6use serde::{Deserialize, Serialize};
7#[cfg(feature = "openapi")]
8use utoipa::ToSchema;
9
10/// Types of source binaries used for package building
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[cfg_attr(feature = "openapi", derive(ToSchema))]
13#[serde(rename_all = "kebab-case")]
14pub enum SourceBinaryType {
15    /// alien-project-cli binary
16    Cli,
17    /// alien-terraform binary
18    Terraform,
19    /// alien-operator binary
20    Operator,
21}
22
23impl SourceBinaryType {
24    /// Returns the binary filename (without extension)
25    pub fn binary_name(&self) -> &'static str {
26        match self {
27            SourceBinaryType::Cli => "alien-project-cli",
28            SourceBinaryType::Terraform => "alien-terraform",
29            SourceBinaryType::Operator => "alien-operator",
30        }
31    }
32}
33
34impl std::fmt::Display for SourceBinaryType {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            SourceBinaryType::Cli => write!(f, "cli"),
38            SourceBinaryType::Terraform => write!(f, "terraform"),
39            SourceBinaryType::Operator => write!(f, "operator"),
40        }
41    }
42}
43
44/// Target OS and architecture for compiled binaries.
45///
46/// Used as keys in package output maps (CLI binaries, Terraform providers, etc.)
47/// and for cross-compilation target selection during builds.
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
49#[cfg_attr(feature = "openapi", derive(ToSchema))]
50#[serde(rename_all = "kebab-case")]
51pub enum BinaryTarget {
52    /// Windows x64 (x86_64-pc-windows-gnu)
53    WindowsX64,
54    /// Linux x86_64 (musl)
55    LinuxX64,
56    /// Linux ARM64 (musl)
57    LinuxArm64,
58    /// macOS ARM64 (Apple Silicon)
59    DarwinArm64,
60}
61
62impl BinaryTarget {
63    /// All supported binary targets
64    pub const ALL: &'static [BinaryTarget] = &[
65        BinaryTarget::WindowsX64,
66        BinaryTarget::LinuxX64,
67        BinaryTarget::LinuxArm64,
68        BinaryTarget::DarwinArm64,
69    ];
70
71    /// Linux-only targets (for container/operator builds)
72    pub const LINUX: &'static [BinaryTarget] = &[BinaryTarget::LinuxX64, BinaryTarget::LinuxArm64];
73
74    /// Get the Rust target triple for this platform
75    pub fn rust_target_triple(&self) -> &'static str {
76        match self {
77            Self::WindowsX64 => "x86_64-pc-windows-gnu",
78            Self::LinuxX64 => "x86_64-unknown-linux-musl",
79            Self::LinuxArm64 => "aarch64-unknown-linux-musl",
80            Self::DarwinArm64 => "aarch64-apple-darwin",
81        }
82    }
83
84    /// Get the binary extension for this platform
85    pub fn binary_extension(&self) -> &'static str {
86        match self {
87            Self::WindowsX64 => ".exe",
88            _ => "",
89        }
90    }
91
92    /// Get the platform identifier for runtime downloads (e.g., "linux-x64")
93    pub fn runtime_platform_id(&self) -> &'static str {
94        match self {
95            Self::WindowsX64 => "windows-x64",
96            Self::LinuxX64 => "linux-x64",
97            Self::LinuxArm64 => "linux-aarch64",
98            Self::DarwinArm64 => "darwin-aarch64",
99        }
100    }
101
102    /// Get the OCI os string for this target
103    pub fn oci_os(&self) -> &'static str {
104        match self {
105            Self::WindowsX64 => "windows",
106            Self::LinuxX64 | Self::LinuxArm64 => "linux",
107            Self::DarwinArm64 => "darwin",
108        }
109    }
110
111    /// Get the OCI architecture string for this target
112    pub fn oci_arch(&self) -> &'static str {
113        match self {
114            Self::WindowsX64 | Self::LinuxX64 => "amd64",
115            Self::LinuxArm64 | Self::DarwinArm64 => "arm64",
116        }
117    }
118
119    /// Get the Bun cross-compilation target for `bun build --compile --target`
120    pub fn bun_target(&self) -> &'static str {
121        match self {
122            Self::WindowsX64 => "bun-windows-x64",
123            Self::LinuxX64 => "bun-linux-x64",
124            Self::LinuxArm64 => "bun-linux-arm64",
125            Self::DarwinArm64 => "bun-darwin-arm64",
126        }
127    }
128
129    /// Terraform registry platform key (os_arch format)
130    pub fn terraform_key(&self) -> &'static str {
131        match self {
132            BinaryTarget::LinuxX64 => "linux_amd64",
133            BinaryTarget::LinuxArm64 => "linux_arm64",
134            BinaryTarget::DarwinArm64 => "darwin_arm64",
135            BinaryTarget::WindowsX64 => "windows_amd64",
136        }
137    }
138
139    /// Terraform OS string
140    pub fn terraform_os(&self) -> &'static str {
141        match self {
142            BinaryTarget::LinuxX64 | BinaryTarget::LinuxArm64 => "linux",
143            BinaryTarget::DarwinArm64 => "darwin",
144            BinaryTarget::WindowsX64 => "windows",
145        }
146    }
147
148    /// Terraform architecture string
149    pub fn terraform_arch(&self) -> &'static str {
150        match self {
151            BinaryTarget::LinuxX64 | BinaryTarget::WindowsX64 => "amd64",
152            BinaryTarget::LinuxArm64 | BinaryTarget::DarwinArm64 => "arm64",
153        }
154    }
155
156    /// Check if this target is a Darwin/macOS target
157    pub fn is_darwin(&self) -> bool {
158        matches!(self, Self::DarwinArm64)
159    }
160
161    /// Check if this is a Windows target
162    pub fn is_windows(&self) -> bool {
163        matches!(self, Self::WindowsX64)
164    }
165
166    /// Get the Linux container target matching the current host architecture.
167    /// Containers always run Linux (even on macOS via Docker's Linux VM),
168    /// so we map the host architecture to the corresponding Linux target.
169    pub fn linux_container_target() -> Self {
170        match Self::current_os() {
171            Self::DarwinArm64 | Self::LinuxArm64 => Self::LinuxArm64,
172            Self::LinuxX64 | Self::WindowsX64 => Self::LinuxX64,
173        }
174    }
175
176    /// Get all possible targets as a Vec
177    pub fn all() -> Vec<Self> {
178        Self::ALL.to_vec()
179    }
180
181    /// Get default targets for a platform
182    pub fn defaults_for_platform(platform: crate::Platform) -> Vec<Self> {
183        match platform {
184            crate::Platform::Aws => vec![Self::LinuxArm64],
185            crate::Platform::Gcp => vec![Self::LinuxX64],
186            crate::Platform::Azure => vec![Self::LinuxX64],
187            crate::Platform::Kubernetes => vec![Self::LinuxArm64],
188            crate::Platform::Local => Self::all(),
189            crate::Platform::Test => vec![Self::LinuxX64],
190        }
191    }
192
193    /// Detect the current OS target
194    pub fn current_os() -> Self {
195        #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
196        return Self::WindowsX64;
197
198        #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
199        return Self::LinuxX64;
200
201        #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
202        return Self::LinuxArm64;
203
204        #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
205        return Self::DarwinArm64;
206
207        #[cfg(not(any(
208            all(target_os = "windows", target_arch = "x86_64"),
209            all(target_os = "linux", target_arch = "x86_64"),
210            all(target_os = "linux", target_arch = "aarch64"),
211            all(target_os = "macos", target_arch = "aarch64")
212        )))]
213        {
214            Self::LinuxX64
215        }
216    }
217}
218
219impl std::fmt::Display for BinaryTarget {
220    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221        match self {
222            BinaryTarget::WindowsX64 => write!(f, "windows-x64"),
223            BinaryTarget::LinuxX64 => write!(f, "linux-x64"),
224            BinaryTarget::LinuxArm64 => write!(f, "linux-arm64"),
225            BinaryTarget::DarwinArm64 => write!(f, "darwin-arm64"),
226        }
227    }
228}
229
230impl std::str::FromStr for BinaryTarget {
231    type Err = String;
232
233    fn from_str(s: &str) -> Result<Self, Self::Err> {
234        match s {
235            "windows-x64" => Ok(BinaryTarget::WindowsX64),
236            "linux-x64" => Ok(BinaryTarget::LinuxX64),
237            "linux-arm64" => Ok(BinaryTarget::LinuxArm64),
238            "darwin-arm64" => Ok(BinaryTarget::DarwinArm64),
239            _ => Err(format!("Unknown binary target: {}", s)),
240        }
241    }
242}