1#![deny(missing_docs)]
2#![allow(clippy::single_match, clippy::result_large_err)]
3
4use std::io::Write;
14
15use announce::TagSettings;
16use axoasset::LocalAsset;
17use axoprocess::Cmd;
18use backend::{
19 ci::CiInfo,
20 installer::{
21 self, macpkg::PkgInstallerInfo, msi::MsiInstallerInfo, HomebrewImpl, InstallerImpl,
22 },
23};
24use build::generic::{build_generic_target, run_extra_artifacts_build};
25use build::{
26 cargo::{build_cargo_target, rustup_toolchain},
27 fake::{build_fake_cargo_target, build_fake_generic_target},
28};
29use camino::{Utf8Path, Utf8PathBuf};
30use cargo_dist_schema::{ArtifactId, ChecksumValue, ChecksumValueRef, DistManifest, TripleName};
31use config::{
32 ArtifactMode, ChecksumStyle, CompressionImpl, Config, DirtyMode, GenerateMode, ZipStyle,
33};
34use console::Term;
35use semver::Version;
36use temp_dir::TempDir;
37use tracing::info;
38
39use errors::*;
40pub use init::{do_init, do_migrate, InitArgs};
41pub use tasks::*;
42
43pub mod announce;
44pub mod backend;
45pub mod build;
46pub mod config;
47pub mod env;
48pub mod errors;
49pub mod host;
50mod init;
51pub mod linkage;
52pub mod manifest;
53pub mod net;
54pub mod platform;
55pub mod sign;
56pub mod tasks;
57#[cfg(test)]
58mod tests;
59
60pub fn do_env_test(cfg: &Config) -> DistResult<()> {
62 let (dist, _manifest) = tasks::gather_work(cfg)?;
63
64 let local_builds = matches!(
65 cfg.artifact_mode,
66 ArtifactMode::Local | ArtifactMode::All | ArtifactMode::Host
67 );
68
69 let builds = dist.config.builds;
70
71 let need_cargo_auditable = builds.cargo.cargo_auditable && local_builds;
73 let need_omnibor = builds.omnibor;
75 let mut need_xwin = false;
76 let mut need_zigbuild = false;
77
78 let tools = dist.tools;
79 let host = tools.host_target.parse()?;
80
81 for step in dist.local_build_steps.iter() {
82 if cfg.artifact_mode == ArtifactMode::Lies {
84 break;
85 }
86
87 match step {
88 BuildStep::Cargo(step) => {
89 let target = step.target_triple.parse()?;
90 let wrapper = tasks::build_wrapper_for_cross(&host, &target)?;
91
92 match wrapper {
93 Some(CargoBuildWrapper::Xwin) => {
94 need_xwin = true;
95 }
96 Some(CargoBuildWrapper::ZigBuild) => {
97 need_zigbuild = true;
98 }
99 None => {}
100 }
101 }
102 _ => {}
103 }
104 }
105
106 let all_tools: Vec<Option<DistResult<&Tool>>> = vec![
111 need_cargo_auditable.then(|| tools.cargo_auditable()),
112 need_omnibor.then(|| tools.omnibor()),
113 need_xwin.then(|| tools.cargo_xwin()),
114 need_zigbuild.then(|| tools.cargo_zigbuild()),
115 ];
116
117 let needed_tools = all_tools.into_iter().flatten();
119
120 let missing: Vec<String> = needed_tools
121 .filter_map(|t| match t {
122 Ok(_) => None,
124 Err(DistError::ToolMissing { tool: ref name }) => Some(name.to_owned()),
126 Err(_) => unreachable!(
129 "do_env_test() got an Err that wasn't DistError::ToolMissing. This is a dist bug."
130 ),
131 })
132 .collect();
133
134 missing
135 .is_empty()
136 .then_some(())
137 .ok_or(DistError::EnvToolsMissing { tools: missing })
138}
139
140pub fn do_build(cfg: &Config) -> DistResult<DistManifest> {
142 do_env_test(cfg)?;
143 check_integrity(cfg)?;
144
145 let (dist, mut manifest) = tasks::gather_work(cfg)?;
146
147 if !dist.dist_dir.exists() {
155 LocalAsset::create_dir_all(&dist.dist_dir)?;
156 }
157
158 eprintln!("building artifacts:");
159 for artifact in &dist.artifacts {
160 eprintln!(" {}", artifact.id);
161 init_artifact_dir(&dist, artifact)?;
162 }
163 eprintln!();
164
165 for step in &dist.local_build_steps {
167 if dist.local_builds_are_lies {
168 build_fake(&dist, step, &mut manifest)?;
169 } else {
170 run_build_step(&dist, step, &mut manifest)?;
171 }
172 }
173
174 for step in &dist.global_build_steps {
176 if dist.local_builds_are_lies {
177 build_fake(&dist, step, &mut manifest)?;
178 } else {
179 run_build_step(&dist, step, &mut manifest)?;
180 }
181 }
182
183 Ok(manifest)
184}
185
186pub fn do_manifest(cfg: &Config) -> DistResult<DistManifest> {
188 check_integrity(cfg)?;
189 let (_dist, manifest) = gather_work(cfg)?;
190
191 Ok(manifest)
192}
193
194fn run_build_step(
196 dist_graph: &DistGraph,
197 target: &BuildStep,
198 manifest: &mut DistManifest,
199) -> DistResult<()> {
200 match target {
201 BuildStep::Generic(target) => build_generic_target(dist_graph, manifest, target)?,
202 BuildStep::Cargo(target) => build_cargo_target(dist_graph, manifest, target)?,
203 BuildStep::Rustup(cmd) => rustup_toolchain(dist_graph, cmd)?,
204 BuildStep::CopyFile(CopyStep {
205 src_path,
206 dest_path,
207 }) => copy_file(src_path, dest_path)?,
208 BuildStep::CopyDir(CopyStep {
209 src_path,
210 dest_path,
211 }) => copy_dir(src_path, dest_path)?,
212 BuildStep::CopyFileOrDir(CopyStep {
213 src_path,
214 dest_path,
215 }) => copy_file_or_dir(src_path, dest_path)?,
216 BuildStep::Zip(ZipDirStep {
217 src_path,
218 dest_path,
219 zip_style,
220 with_root,
221 }) => zip_dir(src_path, dest_path, zip_style, with_root.as_deref())?,
222 BuildStep::GenerateInstaller(installer) => {
223 generate_installer(dist_graph, installer, manifest)?
224 }
225 BuildStep::Checksum(ChecksumImpl {
226 checksum,
227 src_path,
228 dest_path,
229 for_artifact,
230 }) => generate_and_write_checksum(
231 manifest,
232 checksum,
233 src_path,
234 dest_path.as_deref(),
235 for_artifact.as_ref(),
236 )?,
237 BuildStep::UnifiedChecksum(UnifiedChecksumStep {
238 checksum,
239 dest_path,
240 }) => generate_unified_checksum(manifest, *checksum, dest_path)?,
241 BuildStep::OmniborArtifactId(OmniborArtifactIdImpl {
242 src_path,
243 dest_path,
244 }) => generate_omnibor_artifact_id(dist_graph, src_path, dest_path)?,
245 BuildStep::GenerateSourceTarball(SourceTarballStep {
246 committish,
247 prefix,
248 target,
249 working_dir,
250 }) => generate_source_tarball(dist_graph, committish, prefix, target, working_dir)?,
251 BuildStep::Extra(target) => run_extra_artifacts_build(dist_graph, target)?,
252 BuildStep::Updater(updater) => fetch_updater(dist_graph, updater)?,
253 };
254 Ok(())
255}
256
257const AXOUPDATER_ASSET_ROOT: &str = "https://github.com/axodotdev/axoupdater/releases";
258const AXOUPDATER_MINIMUM_VERSION: &str = "0.9.0";
259
260fn axoupdater_latest_asset_root() -> String {
261 format!("{AXOUPDATER_ASSET_ROOT}/latest/download")
262}
263
264fn axoupdater_asset_root() -> String {
265 format!("{AXOUPDATER_ASSET_ROOT}/download/v{}", axoupdater::VERSION)
266}
267
268pub fn fetch_updater(dist_graph: &DistGraph, updater: &UpdaterStep) -> DistResult<()> {
270 let ext = if updater.target_triple.is_windows() {
271 ".zip"
272 } else {
273 ".tar.xz"
274 };
275
276 let asset_root = if updater.use_latest {
277 axoupdater_latest_asset_root()
278 } else {
279 axoupdater_asset_root()
280 };
281
282 let expected_url = format!(
283 "{}/axoupdater-cli-{}{ext}",
284 asset_root, updater.target_triple
285 );
286
287 let handle = tokio::runtime::Handle::current();
288 let resp = handle
289 .block_on(dist_graph.axoclient.head(&expected_url))
290 .map_err(|_| DistError::AxoupdaterReleaseCheckFailed {})?;
291
292 if resp.status().is_success() {
294 fetch_updater_from_binary(dist_graph, updater, &expected_url)
295 } else if resp.status() == axoasset::reqwest::StatusCode::NOT_FOUND {
297 Err(DistError::NoAxoupdaterForTarget {
298 target: updater.target_triple.to_string(),
299 })
300 } else {
302 Err(DistError::AxoupdaterReleaseCheckFailed {})
303 }
304}
305
306pub fn create_tmp() -> DistResult<(TempDir, Utf8PathBuf)> {
309 let tmp_dir = TempDir::new()?;
310 let tmp_root =
311 Utf8PathBuf::from_path_buf(tmp_dir.path().to_owned()).expect("tempdir isn't utf8!?");
312 Ok((tmp_dir, tmp_root))
313}
314
315fn fetch_updater_from_binary(
317 dist_graph: &DistGraph,
318 updater: &UpdaterStep,
319 asset_url: &str,
320) -> DistResult<()> {
321 let (_tmp_dir, tmp_root) = create_tmp()?;
322 let zipball_target = tmp_root.join("archive");
323
324 let handle = tokio::runtime::Handle::current();
325 handle.block_on(
326 dist_graph
327 .axoclient
328 .load_and_write_to_file(asset_url, &zipball_target),
329 )?;
330 let suffix = if updater.target_triple.is_windows() {
331 ".exe"
332 } else {
333 ""
334 };
335 let requested_filename = format!("axoupdater{suffix}");
336
337 let bytes = if asset_url.ends_with(".tar.xz") {
338 LocalAsset::untar_xz_file(&zipball_target, &requested_filename)?
339 } else if asset_url.ends_with(".tar.gz") {
340 LocalAsset::untar_gz_file(&zipball_target, &requested_filename)?
341 } else if asset_url.ends_with(".zip") {
342 LocalAsset::unzip_file(&zipball_target, &requested_filename)?
343 } else {
344 let extension = Utf8PathBuf::from(asset_url)
345 .extension()
346 .unwrap_or("unable to determine")
347 .to_owned();
348 return Err(DistError::UnrecognizedCompression { extension });
349 };
350
351 let target = dist_graph.target_dir.join(&updater.target_filename);
352 std::fs::write(target, bytes)?;
353
354 Ok(())
355}
356
357fn build_fake(
358 dist_graph: &DistGraph,
359 target: &BuildStep,
360 manifest: &mut DistManifest,
361) -> DistResult<()> {
362 match target {
363 BuildStep::Generic(target) => build_fake_generic_target(dist_graph, manifest, target)?,
366 BuildStep::Cargo(target) => build_fake_cargo_target(dist_graph, manifest, target)?,
367 BuildStep::Rustup(_) => {}
369 BuildStep::CopyFile(CopyStep {
371 src_path,
372 dest_path,
373 }) => copy_file(src_path, dest_path)?,
374 BuildStep::CopyDir(CopyStep {
375 src_path,
376 dest_path,
377 }) => copy_dir(src_path, dest_path)?,
378 BuildStep::CopyFileOrDir(CopyStep {
379 src_path,
380 dest_path,
381 }) => copy_file_or_dir(src_path, dest_path)?,
382 BuildStep::Zip(ZipDirStep {
384 src_path,
385 dest_path,
386 zip_style,
387 with_root,
388 }) => zip_dir(src_path, dest_path, zip_style, with_root.as_deref())?,
389 BuildStep::GenerateInstaller(installer) => match installer {
390 InstallerImpl::Msi(msi) => generate_fake_msi(dist_graph, msi, manifest)?,
392 InstallerImpl::Pkg(pkg) => generate_fake_pkg(dist_graph, pkg, manifest)?,
393 _ => generate_installer(dist_graph, installer, manifest)?,
394 },
395 BuildStep::Checksum(ChecksumImpl {
396 checksum,
397 src_path,
398 dest_path,
399 for_artifact,
400 }) => generate_and_write_checksum(
401 manifest,
402 checksum,
403 src_path,
404 dest_path.as_deref(),
405 for_artifact.as_ref(),
406 )?,
407 BuildStep::UnifiedChecksum(UnifiedChecksumStep {
408 checksum,
409 dest_path,
410 }) => generate_unified_checksum(manifest, *checksum, dest_path)?,
411 BuildStep::OmniborArtifactId(OmniborArtifactIdImpl {
412 src_path,
413 dest_path,
414 }) => generate_omnibor_artifact_id(dist_graph, src_path, dest_path)?,
415 BuildStep::GenerateSourceTarball(SourceTarballStep {
423 committish,
424 prefix,
425 target,
426 working_dir,
427 }) => generate_fake_source_tarball(dist_graph, committish, prefix, target, working_dir)?,
428 BuildStep::Extra(target) => run_fake_extra_artifacts_build(dist_graph, target)?,
430 BuildStep::Updater(_) => unimplemented!(),
431 }
432 Ok(())
433}
434
435fn run_fake_extra_artifacts_build(dist: &DistGraph, target: &ExtraBuildStep) -> DistResult<()> {
436 for artifact in &target.artifact_relpaths {
437 let path = dist.dist_dir.join(artifact);
438 LocalAsset::write_new_all("", &path)?;
439 }
440
441 Ok(())
442}
443
444fn generate_fake_msi(
445 _dist: &DistGraph,
446 msi: &MsiInstallerInfo,
447 _manifest: &DistManifest,
448) -> DistResult<()> {
449 LocalAsset::write_new_all("", &msi.file_path)?;
450
451 Ok(())
452}
453
454fn generate_fake_pkg(
455 _dist: &DistGraph,
456 pkg: &PkgInstallerInfo,
457 _manifest: &DistManifest,
458) -> DistResult<()> {
459 LocalAsset::write_new_all("", &pkg.file_path)?;
460
461 Ok(())
462}
463
464fn generate_omnibor_artifact_id(
465 dist_graph: &DistGraph,
466 src_path: &Utf8Path,
467 dest_path: &Utf8Path,
468) -> DistResult<()> {
469 let omnibor = dist_graph.tools.omnibor()?;
470 let mut cmd = Cmd::new(&omnibor.cmd, "generate an OmniBOR Artifact ID");
471 cmd.arg("artifact")
472 .arg("id")
473 .arg("--format")
474 .arg("short")
475 .arg("--path")
476 .arg(src_path);
477
478 let output = cmd.output()?.stdout;
479 let output = String::from_utf8_lossy(&output);
480
481 LocalAsset::write_new_all(&output, dest_path)?;
482
483 Ok(())
484}
485
486fn generate_and_write_checksum(
488 manifest: &mut DistManifest,
489 checksum: &ChecksumStyle,
490 src_path: &Utf8Path,
491 dest_path: Option<&Utf8Path>,
492 for_artifact: Option<&ArtifactId>,
493) -> DistResult<()> {
494 let output = generate_checksum(checksum, src_path)?;
495 if let Some(dest_path) = dest_path {
496 let name = src_path.file_name().expect("hashing file with no name!?");
497 write_checksum_file(&[(name, &output)], dest_path)?;
498 }
499 if let Some(artifact_id) = for_artifact {
500 if let Some(artifact) = manifest.artifacts.get_mut(artifact_id) {
501 artifact.checksums.insert(checksum.ext().to_owned(), output);
502 }
503 }
504 Ok(())
505}
506
507fn generate_unified_checksum(
509 manifest: &DistManifest,
510 checksum: ChecksumStyle,
511 dest_path: &Utf8Path,
512) -> DistResult<()> {
513 let expected_checksum_ext = checksum.ext();
514 let mut entries: Vec<(&str, &ChecksumValueRef)> = vec![];
515
516 for artifact in manifest.artifacts.values() {
517 let artifact_name = if let Some(artifact_name) = artifact.name.as_deref() {
518 artifact_name
519 } else {
520 continue;
521 };
522
523 for (checksum_ext, checksum) in &artifact.checksums {
524 if checksum_ext == expected_checksum_ext {
525 entries.push((artifact_name.as_str(), checksum));
526 }
527 }
528 }
529 write_checksum_file(&entries, dest_path)?;
530
531 Ok(())
532}
533
534fn generate_checksum(checksum: &ChecksumStyle, src_path: &Utf8Path) -> DistResult<ChecksumValue> {
536 info!("generating {checksum:?} for {src_path}");
537 use sha2::Digest;
538 use std::fmt::Write;
539
540 let file_bytes = axoasset::LocalAsset::load_bytes(src_path.as_str())?;
541
542 let hash = match checksum {
543 ChecksumStyle::Sha256 => {
544 let mut hasher = sha2::Sha256::new();
545 hasher.update(&file_bytes);
546 hasher.finalize().as_slice().to_owned()
547 }
548 ChecksumStyle::Sha512 => {
549 let mut hasher = sha2::Sha512::new();
550 hasher.update(&file_bytes);
551 hasher.finalize().as_slice().to_owned()
552 }
553 ChecksumStyle::Sha3_256 => {
554 let mut hasher = sha3::Sha3_256::new();
555 hasher.update(&file_bytes);
556 hasher.finalize().as_slice().to_owned()
557 }
558 ChecksumStyle::Sha3_512 => {
559 let mut hasher = sha3::Sha3_512::new();
560 hasher.update(&file_bytes);
561 hasher.finalize().as_slice().to_owned()
562 }
563 ChecksumStyle::Blake2s => {
564 let mut hasher = blake2::Blake2s256::new();
565 hasher.update(&file_bytes);
566 hasher.finalize().as_slice().to_owned()
567 }
568 ChecksumStyle::Blake2b => {
569 let mut hasher = blake2::Blake2b512::new();
570 hasher.update(&file_bytes);
571 hasher.finalize().as_slice().to_owned()
572 }
573 ChecksumStyle::False => {
574 unreachable!()
575 }
576 };
577 let mut output = String::with_capacity(hash.len() * 2);
578 for byte in hash {
579 write!(&mut output, "{:02x}", byte).unwrap();
580 }
581 Ok(ChecksumValue::new(output))
582}
583
584fn generate_source_tarball(
588 graph: &DistGraph,
589 committish: &str,
590 prefix: &str,
591 target: &Utf8Path,
592 working_dir: &Utf8Path,
593) -> DistResult<()> {
594 let git = if let Some(tool) = &graph.tools.git {
595 tool.cmd.to_owned()
596 } else {
597 return Err(DistError::ToolMissing {
598 tool: "git".to_owned(),
599 });
600 };
601
602 Cmd::new(git, "generate a source tarball for your project")
603 .arg("archive")
604 .arg(committish)
605 .arg("--format=tar.gz")
606 .arg("--prefix")
607 .arg(prefix)
608 .arg("--output")
609 .arg(target)
610 .current_dir(working_dir)
611 .run()?;
612
613 Ok(())
614}
615
616fn generate_fake_source_tarball(
617 _graph: &DistGraph,
618 _committish: &str,
619 _prefix: &str,
620 target: &Utf8Path,
621 _working_dir: &Utf8Path,
622) -> DistResult<()> {
623 LocalAsset::write_new_all("", target)?;
624
625 Ok(())
626}
627
628fn write_checksum_file(
630 entries: &[(&str, &ChecksumValueRef)],
631 dest_path: &Utf8Path,
632) -> DistResult<()> {
633 let mut contents = String::new();
645 for (file_path, checksum) in entries {
646 use std::fmt::Write;
647 writeln!(&mut contents, "{checksum} *{file_path}",).unwrap();
648 }
649 contents.push('\n');
651
652 axoasset::LocalAsset::write_new(&contents, dest_path)?;
653 Ok(())
654}
655
656fn init_artifact_dir(_dist: &DistGraph, artifact: &Artifact) -> DistResult<()> {
658 if artifact.file_path.exists() {
660 LocalAsset::remove_file(&artifact.file_path)?;
661 }
662
663 let Some(archive) = &artifact.archive else {
664 return Ok(());
666 };
667 info!("recreating artifact dir: {}", archive.dir_path);
668
669 if archive.dir_path.exists() {
671 LocalAsset::remove_dir_all(&archive.dir_path)?;
672 }
673 LocalAsset::create_dir(&archive.dir_path)?;
674
675 Ok(())
676}
677
678pub(crate) fn copy_file(src_path: &Utf8Path, dest_path: &Utf8Path) -> DistResult<()> {
679 LocalAsset::copy_file_to_file(src_path, dest_path)?;
680 Ok(())
681}
682
683pub(crate) fn copy_dir(src_path: &Utf8Path, dest_path: &Utf8Path) -> DistResult<()> {
684 LocalAsset::copy_dir_to_dir(src_path, dest_path)?;
685 Ok(())
686}
687
688pub(crate) fn copy_file_or_dir(src_path: &Utf8Path, dest_path: &Utf8Path) -> DistResult<()> {
689 if src_path.is_dir() {
690 copy_dir(src_path, dest_path)
691 } else {
692 copy_file(src_path, dest_path)
693 }
694}
695
696fn zip_dir(
697 src_path: &Utf8Path,
698 dest_path: &Utf8Path,
699 zip_style: &ZipStyle,
700 with_root: Option<&Utf8Path>,
701) -> DistResult<()> {
702 match zip_style {
703 ZipStyle::Zip => LocalAsset::zip_dir(src_path, dest_path, with_root)?,
704 ZipStyle::Tar(CompressionImpl::Gzip) => {
705 LocalAsset::tar_gz_dir(src_path, dest_path, with_root)?
706 }
707 ZipStyle::Tar(CompressionImpl::Xzip) => {
708 LocalAsset::tar_xz_dir(src_path, dest_path, with_root)?
709 }
710 ZipStyle::Tar(CompressionImpl::Zstd) => {
711 LocalAsset::tar_zstd_dir(src_path, dest_path, with_root)?
712 }
713 ZipStyle::TempDir => {
714 }
716 }
717 Ok(())
718}
719
720#[derive(Debug)]
722pub struct GenerateArgs {
723 pub check: bool,
725 pub modes: Vec<GenerateMode>,
727}
728
729fn do_generate_preflight_checks(dist: &DistGraph) -> DistResult<()> {
730 if let Some(desired_version) = &dist.config.dist_version {
738 let current_version: Version = std::env!("CARGO_PKG_VERSION").parse().unwrap();
739 if desired_version != ¤t_version
740 && !desired_version.pre.starts_with("github-")
741 && !matches!(dist.allow_dirty, DirtyMode::AllowAll)
742 {
743 return Err(DistError::MismatchedDistVersion {
744 config_version: desired_version.to_string(),
745 running_version: current_version.to_string(),
746 });
747 }
748 }
749 if !dist.is_init {
750 return Err(DistError::NeedsInit);
751 }
752
753 Ok(())
754}
755
756pub fn do_generate(cfg: &Config, args: &GenerateArgs) -> DistResult<()> {
758 let (dist, _manifest) = gather_work(cfg)?;
759
760 run_generate(&dist, args)?;
761
762 Ok(())
763}
764
765pub fn run_generate(dist: &DistGraph, args: &GenerateArgs) -> DistResult<()> {
767 do_generate_preflight_checks(dist)?;
768
769 let inferred = args.modes.is_empty();
772 let modes = if inferred {
773 &[GenerateMode::Ci, GenerateMode::Msi]
774 } else {
775 for &mode in &args.modes {
777 if !dist.allow_dirty.should_run(mode)
778 && matches!(dist.allow_dirty, DirtyMode::AllowList(..))
779 {
780 Err(DistError::ContradictoryGenerateModes {
781 generate_mode: mode,
782 })?;
783 }
784 }
785 &args.modes[..]
786 };
787
788 for &mode in modes {
791 if dist.allow_dirty.should_run(mode) {
792 match mode {
793 GenerateMode::Ci => {
794 let CiInfo { github } = &dist.ci;
796 if let Some(github) = github {
797 if args.check {
798 github.check(dist)?;
799 } else {
800 github.write_to_disk(dist)?;
801 }
802 }
803 }
804 GenerateMode::Msi => {
805 for artifact in &dist.artifacts {
806 if let ArtifactKind::Installer(InstallerImpl::Msi(msi)) = &artifact.kind {
807 if args.check {
808 msi.check_config()?;
809 } else {
810 msi.write_config_to_disk()?;
811 }
812 }
813 }
814 }
815 }
816 }
817 }
818
819 Ok(())
820}
821
822pub fn check_integrity(cfg: &Config) -> DistResult<()> {
826 let check_config = Config {
829 tag_settings: TagSettings {
831 needs_coherence: false,
832 tag: cfg.tag_settings.tag.clone(),
837 },
838 create_hosting: false,
840 artifact_mode: ArtifactMode::All,
841 no_local_paths: false,
842 allow_all_dirty: cfg.allow_all_dirty,
843 targets: vec![],
844 ci: vec![],
845 installers: vec![],
846 root_cmd: "check".to_owned(),
847 };
848 let (dist, _manifest) = tasks::gather_work(&check_config)?;
849
850 if let Some(hosting) = &dist.hosting {
851 if hosting.hosts.contains(&config::HostingStyle::Axodotdev) {
852 let mut out = Term::stderr();
853 let info = "INFO:";
854 let message = r"You've enabled Axo Releases, which is currently in Closed Beta.
855If you haven't yet signed up, please join our discord
856(https://discord.gg/ECnWuUUXQk) or message hello@axo.dev to get started!
857";
858
859 writeln!(out, "{} {}", out.style().yellow().apply_to(info), message).unwrap();
860 }
861 }
862
863 run_generate(
864 &dist,
865 &GenerateArgs {
866 modes: vec![],
867 check: true,
868 },
869 )
870}
871
872fn generate_installer(
874 dist: &DistGraph,
875 style: &InstallerImpl,
876 manifest: &DistManifest,
877) -> DistResult<()> {
878 match style {
879 InstallerImpl::Shell(info) => {
880 installer::shell::write_install_sh_script(dist, info, manifest)?
881 }
882 InstallerImpl::Powershell(info) => {
883 installer::powershell::write_install_ps_script(dist, info)?
884 }
885 InstallerImpl::Npm(info) => installer::npm::write_npm_project(dist, info)?,
886 InstallerImpl::Homebrew(HomebrewImpl { info, fragments }) => {
887 installer::homebrew::write_homebrew_formula(dist, info, fragments, manifest)?
888 }
889 InstallerImpl::Msi(info) => info.build(dist)?,
890 InstallerImpl::Pkg(info) => info.build()?,
891 }
892 Ok(())
893}
894
895pub fn default_desktop_targets() -> Vec<TripleName> {
897 use crate::platform::targets as t;
898
899 vec![
900 t::TARGET_X64_LINUX_GNU.to_owned(),
902 t::TARGET_X64_WINDOWS.to_owned(),
903 t::TARGET_X64_MAC.to_owned(),
904 t::TARGET_ARM64_MAC.to_owned(),
905 t::TARGET_ARM64_LINUX_GNU.to_owned(),
906 ]
909}
910
911pub fn known_desktop_targets() -> Vec<TripleName> {
913 use crate::platform::targets as t;
914
915 vec![
916 t::TARGET_X64_LINUX_GNU.to_owned(),
918 t::TARGET_X64_LINUX_MUSL.to_owned(),
919 t::TARGET_X64_WINDOWS.to_owned(),
920 t::TARGET_X64_MAC.to_owned(),
921 t::TARGET_ARM64_MAC.to_owned(),
922 t::TARGET_ARM64_LINUX_GNU.to_owned(),
923 t::TARGET_ARM64_WINDOWS.to_owned(),
924 ]
925}