crossbuild_core/
registry.rs1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4use crate::error::CrossBuildError;
5use crate::model::{BuildRequest, HostInfo, TargetTriple};
6use crate::provider::{
7 LinkerProvider, LinkerResolution, SysrootProvider, SysrootResolution, ToolchainProvider,
8 ToolchainResolution,
9};
10
11#[derive(Default)]
13pub struct ProviderRegistry {
14 toolchain_providers: Vec<Arc<dyn ToolchainProvider>>,
15 sysroot_providers: Vec<Arc<dyn SysrootProvider>>,
16 linker_providers: Vec<Arc<dyn LinkerProvider>>,
17}
18
19impl std::fmt::Debug for ProviderRegistry {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.debug_struct("ProviderRegistry")
22 .field("toolchain_providers", &self.toolchain_provider_names())
23 .field("sysroot_providers", &self.sysroot_provider_names())
24 .field("linker_providers", &self.linker_provider_names())
25 .finish()
26 }
27}
28
29impl ProviderRegistry {
30 pub fn new() -> Self {
32 Self {
33 toolchain_providers: Vec::new(),
34 sysroot_providers: Vec::new(),
35 linker_providers: Vec::new(),
36 }
37 }
38
39 pub fn register_toolchain(&mut self, provider: Box<dyn ToolchainProvider>) {
41 self.toolchain_providers.push(Arc::from(provider));
42 self.toolchain_providers.sort_by_key(|p| -p.priority());
43 }
44
45 pub fn register_sysroot(&mut self, provider: Box<dyn SysrootProvider>) {
47 self.sysroot_providers.push(Arc::from(provider));
48 self.sysroot_providers.sort_by_key(|p| -p.priority());
49 }
50
51 pub fn register_linker(&mut self, provider: Box<dyn LinkerProvider>) {
53 self.linker_providers.push(Arc::from(provider));
54 self.linker_providers.sort_by_key(|p| -p.priority());
55 }
56
57 pub fn resolve_toolchain(
59 &self,
60 target: &TargetTriple,
61 host: &HostInfo,
62 request: &BuildRequest,
63 ) -> Result<ToolchainResolution, CrossBuildError> {
64 for provider in &self.toolchain_providers {
65 if provider.can_provide(target, host) {
66 return provider.resolve(target, host, request);
67 }
68 }
69
70 Err(CrossBuildError::ProviderNotFound {
71 provider_type: "toolchain".to_string(),
72 target: target.triple.clone(),
73 })
74 }
75
76 pub fn resolve_sysroot(
78 &self,
79 target: &TargetTriple,
80 host: &HostInfo,
81 request: &BuildRequest,
82 ) -> Result<Option<SysrootResolution>, CrossBuildError> {
83 for provider in &self.sysroot_providers {
84 if provider.can_provide(target, host) {
85 let res = provider.resolve(target, host, request);
86 match res {
87 Ok(resolution) => return Ok(Some(resolution)),
88 Err(CrossBuildError::SysrootNotNeeded) => return Ok(None),
89 Err(e) => return Err(e),
90 }
91 }
92 }
93 Ok(None)
94 }
95
96 pub fn resolve_linker(
98 &self,
99 target: &TargetTriple,
100 host: &HostInfo,
101 request: &BuildRequest,
102 ) -> Result<LinkerResolution, CrossBuildError> {
103 for provider in &self.linker_providers {
104 if provider.can_provide(target, host) {
105 return provider.resolve(target, host, request);
106 }
107 }
108
109 Err(CrossBuildError::ProviderNotFound {
110 provider_type: "linker".to_string(),
111 target: target.triple.clone(),
112 })
113 }
114
115 pub fn toolchain_provider_names(&self) -> Vec<&str> {
117 self.toolchain_providers.iter().map(|p| p.name()).collect()
118 }
119
120 pub fn sysroot_provider_names(&self) -> Vec<&str> {
122 self.sysroot_providers.iter().map(|p| p.name()).collect()
123 }
124
125 pub fn linker_provider_names(&self) -> Vec<&str> {
127 self.linker_providers.iter().map(|p| p.name()).collect()
128 }
129
130 pub fn get_toolchain_provider(&self, name: &str) -> Option<&Arc<dyn ToolchainProvider>> {
132 self.toolchain_providers.iter().find(|p| p.name() == name)
133 }
134
135 pub fn get_sysroot_provider(&self, name: &str) -> Option<&Arc<dyn SysrootProvider>> {
137 self.sysroot_providers.iter().find(|p| p.name() == name)
138 }
139
140 pub fn get_linker_provider(&self, name: &str) -> Option<&Arc<dyn LinkerProvider>> {
142 self.linker_providers.iter().find(|p| p.name() == name)
143 }
144
145 pub fn resolve_all(
147 &self,
148 target: &TargetTriple,
149 host: &HostInfo,
150 request: &BuildRequest,
151 ) -> Result<CompleteResolution, CrossBuildError> {
152 let toolchain = self.resolve_toolchain(target, host, request)?;
153 let sysroot = self.resolve_sysroot(target, host, request)?;
154 let linker = self.resolve_linker(target, host, request)?;
155
156 Ok(CompleteResolution {
157 toolchain,
158 sysroot,
159 linker,
160 })
161 }
162}
163
164#[derive(Debug, Clone)]
166pub struct CompleteResolution {
167 pub toolchain: ToolchainResolution,
168 pub sysroot: Option<SysrootResolution>,
169 pub linker: LinkerResolution,
170}
171
172impl CompleteResolution {
173 pub fn merged_env(&self) -> BTreeMap<String, String> {
175 let mut env = BTreeMap::new();
176 env.extend(self.toolchain.env.clone());
177 env.extend(self.linker.env.clone());
178 if let Some(ref sysroot) = self.sysroot {
179 env.extend(sysroot.env.clone());
180 }
181 env
182 }
183}