Skip to content

Commit 330935b

Browse files
authored
Merge pull request #71 from slp/macos-workaround-dyld
Re-execute itself with DYLD_LIBRARY_PATH
2 parents 3cdfe0f + 8ad6319 commit 330935b

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ libc = "0.2.82"
1515
serde = "1.0.120"
1616
serde_derive = "1.0.120"
1717
text_io = "0.1.8"
18-
nix = {version = "0.27.1", features = ["socket", "fs"]}
18+
nix = {version = "0.27.1", features = ["socket", "fs", "process"]}

src/main.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use std::collections::HashMap;
5+
use std::env;
6+
use std::ffi::CString;
57
#[cfg(target_os = "macos")]
68
use std::fs::File;
79
#[cfg(target_os = "macos")]
8-
use std::io::{self, Read, Write};
10+
use std::io::{self, Error, ErrorKind, Read, Write};
11+
use std::os::unix::ffi::OsStringExt;
912

1013
use crate::commands::{
1114
ChangeVmCmd, ConfigCmd, CreateCmd, DeleteCmd, InspectCmd, ListCmd, StartCmd,
1215
};
1316
use clap::{Parser, Subcommand};
17+
use nix::unistd::execve;
1418
use serde_derive::{Deserialize, Serialize};
1519
#[cfg(target_os = "macos")]
1620
use text_io::read;
@@ -169,7 +173,62 @@ enum Command {
169173
Config(ConfigCmd),
170174
}
171175

176+
#[cfg(target_os = "macos")]
177+
fn get_brew_prefix() -> Option<String> {
178+
let output = std::process::Command::new("brew")
179+
.arg("--prefix")
180+
.stderr(std::process::Stdio::inherit())
181+
.output()
182+
.ok()?;
183+
184+
let exit_code = output.status.code().unwrap_or(-1);
185+
if exit_code != 0 {
186+
return None;
187+
}
188+
189+
Some(std::str::from_utf8(&output.stdout).ok()?.trim().to_string())
190+
}
191+
192+
#[cfg(target_os = "macos")]
193+
fn reexec() -> Result<(), Error> {
194+
let args: Vec<CString> = env::args_os()
195+
.map(|arg| CString::new(arg.into_vec()).unwrap())
196+
.collect();
197+
198+
let mut envs: Vec<CString> = env::vars_os()
199+
.map(|(key, value)| {
200+
CString::new(format!(
201+
"{}={}",
202+
key.into_string().unwrap(),
203+
value.into_string().unwrap()
204+
))
205+
.unwrap()
206+
})
207+
.collect();
208+
let brew_prefix = get_brew_prefix().ok_or(ErrorKind::NotFound)?;
209+
envs.push(CString::new(format!(
210+
"DYLD_LIBRARY_PATH={brew_prefix}/lib"
211+
))?);
212+
213+
// Use execve to replace the current process. This function only returns
214+
// if an error occurs.
215+
match execve(&args[0], &args, &envs) {
216+
Ok(_) => Ok(()),
217+
Err(e) => {
218+
eprintln!("Error re-executing krunvm: {}", e);
219+
std::process::exit(-1);
220+
}
221+
}
222+
}
223+
172224
fn main() {
225+
#[cfg(target_os = "macos")]
226+
{
227+
if env::var("DYLD_LIBRARY_PATH").is_err() {
228+
_ = reexec();
229+
}
230+
}
231+
173232
let mut cfg: KrunvmConfig = confy::load(APP_NAME).unwrap();
174233
let cli_args = Cli::parse();
175234

0 commit comments

Comments
 (0)