assemble_rust/
rustup.rs

1//! Rustup related tasks
2//!
3
4use log::info;
5
6use assemble_core::dependencies::configurations::Configuration;
7use assemble_core::error::PayloadError;
8use assemble_core::exception::BuildException;
9
10use assemble_core::file_collection::FileCollection;
11
12use assemble_core::plugins::extensions::ExtensionAware;
13
14use assemble_core::project::error::{ProjectError, ProjectResult};
15use assemble_core::task::create_task::CreateTask;
16
17use assemble_core::task::up_to_date::UpToDate;
18
19use assemble_std::dependencies::web::{WebDependency, WebRegistry};
20use assemble_std::specs::exec_spec::Output;
21
22use assemble_std::ProjectExec;
23
24use crate::extensions::RustPluginExtension;
25use crate::plugin::RustBasePlugin;
26use crate::prelude::*;
27use crate::rustup::install::InstallToolchain;
28
29pub mod install;
30
31/// Configure a project to support rustup-related tasks
32pub fn configure_rustup_tasks(project: &mut Project) -> ProjectResult<()> {
33    let mut install = project
34        .task_container_mut()
35        .register_task::<Empty>("install-rustup")?;
36
37    install.configure_with(|t, _| {
38        t.set_description("installs rustup on to the system if not already present");
39        t.set_group("rustup");
40
41        t.up_to_date(|_| which::which("rustup").is_ok());
42
43        Ok(())
44    })?;
45
46    let rustup_install_config = if cfg!(windows) {
47        configure_windows_install(project)?
48    } else if cfg!(unix) {
49        configure_unix_install(project)?
50    } else {
51        return Err(ProjectError::custom("unsupported os for rustup").into());
52    };
53
54    install.configure_with(move |task, _project| -> ProjectResult<()> {
55        task.depends_on(rustup_install_config.clone());
56        task.do_first(move |_task, project| {
57            if which::which("rustup").is_ok() {
58                return Err(BuildException::StopTask.into());
59            }
60
61            let configuration = rustup_install_config
62                .resolved()
63                .map_err(|e| PayloadError::<ProjectError>::new(e))?;
64            let rustup_init_file = configuration.files().into_iter().next().unwrap();
65            println!("rustup file = {:?}", rustup_init_file);
66
67            match project.exec_with(move |exec| {
68                exec.exec(rustup_init_file)
69                    .args(["--default-toolchain", "none"])
70                    .args(["--profile", "minimal"])
71                    .arg("-v")
72                    .stdout(Output::Bytes)
73                    .stderr(Output::Bytes);
74            }) {
75                Ok(handle) => {
76                    let string = handle
77                        .utf8_string_err()
78                        .unwrap()
79                        .map_err(PayloadError::<ProjectError>::new)?;
80                    info!("rustup log: {}", string);
81                    if string.contains("error: cannot install while Rust is installed") {
82                        info!("assuming ok");
83                        return Ok(());
84                    }
85                    if !handle.success() {
86                        return Err(BuildException::custom(
87                            "installing rustup fail. Check console log for more info.",
88                        )
89                        .into());
90                    }
91                }
92                Err(e) => return Err(BuildException::from(e).into()),
93            }
94
95            Ok(())
96        })?;
97
98        Ok(())
99    })?;
100    project
101        .task_container_mut()
102        .register_task_with::<InstallToolchain, _>(
103            RustBasePlugin::INSTALL_DEFAULT_TOOLCHAIN,
104            |t, p| {
105                t.set_description("installs the default toolchain used by this project");
106                t.set_group("rustup");
107
108                let extension = p.extension::<RustPluginExtension>().unwrap();
109                t.depends_on(install);
110                t.toolchain.set_with(extension.toolchain.clone())?;
111                Ok(())
112            },
113        )?;
114
115    Ok(())
116}
117
118fn configure_unix_install(project: &mut Project) -> ProjectResult<Configuration> {
119    project.registries_mut(|reg| {
120        let registry = WebRegistry::new("rust-site", "https://sh.rustup.rs/").unwrap();
121        reg.add_registry(registry);
122        Ok(())
123    })?;
124    let rustup_install_config = project
125        .configurations_mut()
126        .create_with("rustupInstall", |config| {
127            config.add_dependency(
128                WebDependency::new("", "rust-site").with_file_name("rustup-startup.sh"),
129            )
130        })
131        .clone();
132
133    Ok(rustup_install_config)
134}
135
136fn configure_windows_install(project: &mut Project) -> ProjectResult<Configuration> {
137    project.registries_mut(|reg| {
138        let registry = WebRegistry::new("rust-site", "https://static.rust-lang.org/").unwrap();
139        reg.add_registry(registry);
140        Ok(())
141    })?;
142    let rustup_install_config = project
143        .configurations_mut()
144        .create_with("rustup-install", |config| {
145            #[cfg(target_pointer_width = "64")]
146            config.add_dependency(WebDependency::new(
147                "/rustup/dist/x86_64-pc-windows-msvc/rustup-startup.exe",
148                "rust-site",
149            ));
150            #[cfg(target_pointer_width = "32")]
151            config.add_dependency(WebDependency::new(
152                "/rustup/dist/i686-pc-windows-msvc/rustup-startup.exe",
153                "rust-site",
154            ));
155        })
156        .clone();
157
158    Ok(rustup_install_config)
159}