Skip to content

Commit

Permalink
feat(erlang): use precompiled binaries for macos (#3353)
Browse files Browse the repository at this point in the history
Fixes #2721
  • Loading branch information
jdx authored Dec 4, 2024
1 parent 754cace commit 1727515
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 27 deletions.
7 changes: 7 additions & 0 deletions docs/lang/erlang.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ See available versions with `mise ls-remote erlang`.

The plugin uses [kerl](https://github.com/kerl/kerl) under the hood to build erlang.
See kerl's docs for information on configuring kerl.

## Settings

<script setup>
import Settings from '/components/settings.vue';
</script>
<Settings child="erlang" :level="3" />
9 changes: 9 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@
"description": "Path to a file containing environment variables.",
"type": "string"
},
"erlang": {
"additionalProperties": false,
"properties": {
"compile": {
"description": "If true, compile erlang from source. If false, use precompiled binaries. If not set, use precompiled binaries if available.",
"type": "boolean"
}
}
},
"exec_auto_install": {
"default": true,
"description": "Automatically install missing tools when running `mise x`.",
Expand Down
6 changes: 6 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ optional = true
description = "Path to a file containing environment variables."
hide = true

[erlang.compile]
env = "MISE_ERLANG_COMPILE"
type = "Bool"
optional = true
description = "If true, compile erlang from source. If false, use precompiled binaries. If not set, use precompiled binaries if available."

[exec_auto_install]
env = "MISE_EXEC_AUTO_INSTALL"
type = "Bool"
Expand Down
3 changes: 3 additions & 0 deletions src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ impl Settings {
if settings.python.compile.is_none() {
settings.python.compile = Some(true);
}
if settings.erlang.compile.is_none() {
settings.erlang.compile = Some(true);
}
}
settings.set_hidden_configs();
let settings = Arc::new(settings);
Expand Down
128 changes: 101 additions & 27 deletions src/plugins/core/erlang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use std::path::PathBuf;

use crate::backend::Backend;
use crate::cli::args::BackendArg;
use crate::file::display_path;
use crate::http::HTTP_FETCH;
use crate::config::SETTINGS;
use crate::file::{display_path, TarOptions};
use crate::http::{HTTP, HTTP_FETCH};
use crate::install_context::InstallContext;
use crate::lock_file::LockFile;
use crate::toolset::{ToolRequest, ToolVersion};
use crate::{cmd, file, plugins};
use crate::{cmd, file, github, plugins};
use eyre::Result;
use xx::regex;

Expand Down Expand Up @@ -66,33 +67,53 @@ impl ErlangPlugin {
file::make_executable(self.kerl_path())?;
Ok(())
}
}

impl Backend for ErlangPlugin {
fn ba(&self) -> &BackendArg {
&self.ba
}
fn _list_remote_versions(&self) -> Result<Vec<String>> {
self.update_kerl()?;
let versions = crate::plugins::core::run_fetch_task_with_timeout(move || {
let output = cmd!(self.kerl_path(), "list", "releases", "all")
.env("KERL_BASE_DIR", self.ba.cache_path.join("kerl"))
.read()?;
let versions = output
.split('\n')
.filter(|s| regex!(r"^[0-9].+$").is_match(s))
.map(|s| s.to_string())
.collect();
Ok(versions)
})?;
Ok(versions)
fn install_precompiled(
&self,
ctx: &InstallContext,
mut tv: ToolVersion,
) -> Result<Option<ToolVersion>> {
if SETTINGS.erlang.compile == Some(false) {
return Ok(None);
}
let release_tag = format!("OTP-{}", tv.version);
let gh_release = match github::get_release("erlef/otp_builds", &release_tag) {
Ok(release) => release,
Err(e) => {
debug!("Failed to get release: {}", e);
return Ok(None);
}
};
let tarball_name = format!("otp-{ARCH}-{OS}.tar.gz");
let asset = match gh_release.assets.iter().find(|a| a.name == tarball_name) {
Some(asset) => asset,
None => {
debug!("No asset found for {}", release_tag);
return Ok(None);
}
};
ctx.pr.set_message(format!("Downloading {}", tarball_name));
let tarball_path = tv.download_path().join(&tarball_name);
HTTP.download_file(
&asset.browser_download_url,
&tarball_path,
Some(ctx.pr.as_ref()),
)?;
self.verify_checksum(ctx, &mut tv, &tarball_path)?;
ctx.pr.set_message(format!("Extracting {}", tarball_name));
file::untar(
&tarball_path,
&tv.install_path(),
&TarOptions {
strip_components: 0,
pr: Some(ctx.pr.as_ref()),
format: file::TarFormat::TarGz,
},
)?;
Ok(Some(tv))
}

fn install_version_(
&self,
_ctx: &InstallContext,
tv: ToolVersion,
) -> eyre::Result<ToolVersion> {
fn install_via_kerl(&self, _ctx: &InstallContext, tv: ToolVersion) -> Result<ToolVersion> {
self.update_kerl()?;

file::remove_all(tv.install_path())?;
Expand All @@ -117,3 +138,56 @@ impl Backend for ErlangPlugin {
Ok(tv)
}
}

impl Backend for ErlangPlugin {
fn ba(&self) -> &BackendArg {
&self.ba
}
fn _list_remote_versions(&self) -> Result<Vec<String>> {
let versions = if SETTINGS.erlang.compile == Some(false) {
github::list_releases("erlef/otp_builds")?
.into_iter()
.filter_map(|r| r.tag_name.strip_prefix("OTP-").map(|s| s.to_string()))
.collect()
} else {
self.update_kerl()?;
plugins::core::run_fetch_task_with_timeout(move || {
let output = cmd!(self.kerl_path(), "list", "releases", "all")
.env("KERL_BASE_DIR", self.ba.cache_path.join("kerl"))
.read()?;
let versions = output
.split('\n')
.filter(|s| regex!(r"^[0-9].+$").is_match(s))
.map(|s| s.to_string())
.collect();
Ok(versions)
})?
};
Ok(versions)
}

fn install_version_(&self, ctx: &InstallContext, tv: ToolVersion) -> Result<ToolVersion> {
if let Some(tv) = self.install_precompiled(ctx, tv.clone())? {
return Ok(tv);
}
self.install_via_kerl(ctx, tv)
}
}

#[cfg(target_arch = "x86_64")]
pub const ARCH: &str = "x86_64";

#[cfg(target_arch = "aarch64")]
const ARCH: &str = "aarch64";

#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
const ARCH: &str = "unknown";

#[cfg(macos)]
const OS: &str = "apple-darwin";

#[cfg(linux)]
const OS: &str = "unknown";

#[cfg(windows)]
const OS: &str = "unknown";

0 comments on commit 1727515

Please sign in to comment.