Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/vfox/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub(crate) fn env_type() -> Option<String> {
if let Ok(val) = std::env::var("MISE_LIBC") {
match val.to_lowercase().as_str() {
"musl" => return Some("musl".to_string()),
"gnu" => return Some("gnu".to_string()),
"glibc" | "gnu" => return Some("gnu".to_string()),
_ => {} // invalid value ignored, fall through to runtime detection
}
}
Expand Down
8 changes: 7 additions & 1 deletion crates/vfox/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub enum PluginSource {
pub struct Plugin {
pub name: String,
pub dir: PathBuf,
pub runtime_env_type: Option<String>,
source: PluginSource,
lua: Lua,
metadata: OnceCell<Metadata>,
Expand All @@ -41,6 +42,7 @@ impl Plugin {
Ok(Self {
name,
dir: dir.to_path_buf(),
runtime_env_type: None,
source: PluginSource::Filesystem(dir.to_path_buf()),
lua,
metadata: OnceCell::new(),
Expand All @@ -57,6 +59,7 @@ impl Plugin {
Ok(Self {
name: name.to_string(),
dir: dummy_dir,
runtime_env_type: None,
source: PluginSource::Embedded(embedded),
lua,
metadata: OnceCell::new(),
Expand Down Expand Up @@ -209,7 +212,10 @@ impl Plugin {

let metadata = self.load_metadata()?;
self.set_global("PLUGIN", metadata.clone())?;
self.set_global("RUNTIME", Runtime::get(self.dir.clone()))?;
self.set_global(
"RUNTIME",
Runtime::get(self.dir.clone(), self.runtime_env_type.as_deref()),
)?;
self.set_global("OS_TYPE", config::os())?;
self.set_global("ARCH_TYPE", config::arch())?;

Expand Down
7 changes: 5 additions & 2 deletions crates/vfox/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ static RUNTIME: Lazy<Mutex<Runtime>> = Lazy::new(|| {
});

impl Runtime {
pub(crate) fn get(plugin_dir_path: PathBuf) -> Runtime {
pub(crate) fn get(plugin_dir_path: PathBuf, env_type_override: Option<&str>) -> Runtime {
let mut runtime = RUNTIME.lock().unwrap().clone();
runtime.plugin_dir_path = plugin_dir_path;
if let Some(env_type) = env_type_override {
runtime.env_type = Some(env_type.to_string());
}
runtime
}

pub(crate) fn with_platform(plugin_dir_path: PathBuf, os: &str, arch: &str) -> Runtime {
let mut runtime = Self::get(plugin_dir_path);
let mut runtime = Self::get(plugin_dir_path, None);
runtime.os = os.to_string();
runtime.arch = arch.to_string();
runtime.env_type = None; // target libc is unknown in cross-platform context
Expand Down
20 changes: 16 additions & 4 deletions crates/vfox/src/vfox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub struct Vfox {
pub cmd_env: Option<IndexMap<String, String>>,
/// Optional GitHub token for Lua http requests to GitHub API endpoints.
pub github_token: Option<String>,
/// Optional runtime env type (`gnu` or `musl`) exposed to plugin hooks.
pub runtime_env_type: Option<String>,
log_tx: Option<mpsc::Sender<String>>,
}

Expand Down Expand Up @@ -123,7 +125,9 @@ impl Vfox {
}

pub fn get_sdk(&self, name: &str) -> Result<Plugin> {
Plugin::from_name_or_dir(name, &self.plugin_dir.join(name))
let mut plugin = Plugin::from_name_or_dir(name, &self.plugin_dir.join(name))?;
plugin.runtime_env_type = self.runtime_env_type.clone();
Ok(plugin)
}

fn get_sdk_with_env(&self, name: &str) -> Result<Plugin> {
Expand All @@ -146,12 +150,16 @@ impl Vfox {
// Check filesystem first - allows user to override embedded plugins
let plugin_dir = self.plugin_dir.join(sdk);
if plugin_dir.exists() {
return Plugin::from_dir(&plugin_dir);
let mut plugin = Plugin::from_dir(&plugin_dir)?;
plugin.runtime_env_type = self.runtime_env_type.clone();
return Ok(plugin);
}

// Fall back to embedded plugin if available
if let Some(embedded) = crate::embedded_plugins::get_embedded_plugin(sdk) {
return Plugin::from_embedded(sdk, embedded);
let mut plugin = Plugin::from_embedded(sdk, embedded)?;
plugin.runtime_env_type = self.runtime_env_type.clone();
return Ok(plugin);
}

// Otherwise install from registry
Expand All @@ -175,7 +183,9 @@ impl Vfox {
debug!("Installing plugin {sdk}");
xx::git::clone(url.as_ref(), &plugin_dir, &Default::default())?;
}
Plugin::from_dir(&plugin_dir)
let mut plugin = Plugin::from_dir(&plugin_dir)?;
plugin.runtime_env_type = self.runtime_env_type.clone();
Ok(plugin)
}

pub fn uninstall_plugin(&self, sdk: &str) -> Result<()> {
Expand Down Expand Up @@ -588,6 +598,7 @@ impl Default for Vfox {
skip_verification: false,
cmd_env: None,
github_token: None,
runtime_env_type: None,
log_tx: None,
}
}
Expand Down Expand Up @@ -615,6 +626,7 @@ mod tests {
skip_verification: false,
cmd_env: None,
github_token: None,
runtime_env_type: None,
log_tx: None,
}
}
Expand Down
3 changes: 3 additions & 0 deletions docs/lang/node.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ mise settings node.flavor=musl
mise settings node.flavor=glibc-217
```

For the common musl case, `mise settings libc=musl` also selects Node's `musl`
flavor when `node.flavor` is unset.

## Settings

<script setup>
Expand Down
14 changes: 7 additions & 7 deletions docs/mise-cookbook/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,21 @@ When the container starts with `~` mounted, users still see the system tools aut
Any tools they install normally go to `~/.local/share/mise/installs` (on the mount) and
take priority over system versions.

## Overriding libc detection with MISE_LIBC
## Overriding libc detection

In minimal Docker images (scratch, busybox, distroless) where no dynamic linker
files exist, mise may not detect whether the system uses musl or glibc. Set `MISE_LIBC`
to force the detection:
files exist, mise may not detect whether the system uses musl or glibc. Set `libc`
or `MISE_LIBC` to force the detection:

```Dockerfile
ENV MISE_LIBC=musl
RUN mise install
```

Valid values are `musl` and `gnu` (case-insensitive). Invalid values are silently
ignored and mise falls back to runtime detection. When the mise binary is compiled
for musl (the default for Linux releases), it will also fall back to musl
automatically when no linker is detected.
Valid values are `musl`, `glibc`, and `gnu` (case-insensitive, with `gnu` treated
as glibc). Invalid values are silently ignored and mise falls back to runtime
detection. When the mise binary is compiled for musl (the default for Linux
releases), it will also fall back to musl automatically when no linker is detected.

## Task to run mise in a Docker container

Expand Down
5 changes: 5 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,11 @@
"type": "string"
}
},
"libc": {
"description": "Libc implementation to use for precompiled Linux binaries.",
"type": "string",
"enum": ["glibc", "gnu", "musl"]
},
"libgit2": {
"default": true,
"description": "Use libgit2 for git operations, set to false to shell out to git.",
Expand Down
14 changes: 14 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,20 @@ parse_env = "set_by_comma"
rust_type = "BTreeSet<String>"
type = "SetString"

[libc]
default_docs = '"glibc" | "musl"'
description = "Libc implementation to use for precompiled Linux binaries."
docs = """
Libc implementation to use for precompiled Linux binaries. This is used by backends that publish
separate glibc and musl builds. If unset, mise will detect the current system's libc.

`gnu` is accepted as an alias for `glibc`.
"""
enum = ["glibc", "gnu", "musl"]
env = "MISE_LIBC"
optional = true
type = "String"

[libgit2]
default = true
description = "Use libgit2 for git operations, set to false to shell out to git."
Expand Down
Loading
Loading