mirror of
https://github.com/lune-org/lune.git
synced 2025-04-21 04:13:57 +01:00
73 lines
2.1 KiB
Rust
73 lines
2.1 KiB
Rust
use std::{
|
|
env::consts::EXE_EXTENSION,
|
|
path::{Path, PathBuf},
|
|
process::ExitCode,
|
|
};
|
|
|
|
use anyhow::{Context, Result};
|
|
use clap::Parser;
|
|
use console::style;
|
|
use tokio::{fs, io::AsyncWriteExt as _};
|
|
|
|
use crate::standalone::metadata::Metadata;
|
|
|
|
/// Build a standalone executable
|
|
#[derive(Debug, Clone, Parser)]
|
|
pub struct BuildCommand {
|
|
/// The path to the input file
|
|
pub input: PathBuf,
|
|
|
|
/// The path to the output file - defaults to the
|
|
/// input file path with an executable extension
|
|
#[clap(short, long)]
|
|
pub output: Option<PathBuf>,
|
|
}
|
|
|
|
impl BuildCommand {
|
|
pub async fn run(self) -> Result<ExitCode> {
|
|
let output_path = self
|
|
.output
|
|
.unwrap_or_else(|| self.input.with_extension(EXE_EXTENSION));
|
|
|
|
let input_path_displayed = self.input.display();
|
|
let output_path_displayed = output_path.display();
|
|
|
|
// Try to read the input file
|
|
let source_code = fs::read(&self.input)
|
|
.await
|
|
.context("failed to read input file")?;
|
|
|
|
// Read the contents of the lune interpreter as our starting point
|
|
println!(
|
|
"Creating standalone binary using {}",
|
|
style(input_path_displayed).green()
|
|
);
|
|
let patched_bin = Metadata::create_env_patched_bin(source_code.clone())
|
|
.await
|
|
.context("failed to create patched binary")?;
|
|
|
|
// And finally write the patched binary to the output file
|
|
println!(
|
|
"Writing standalone binary to {}",
|
|
style(output_path_displayed).blue()
|
|
);
|
|
write_executable_file_to(output_path, patched_bin).await?;
|
|
|
|
Ok(ExitCode::SUCCESS)
|
|
}
|
|
}
|
|
|
|
async fn write_executable_file_to(path: impl AsRef<Path>, bytes: impl AsRef<[u8]>) -> Result<()> {
|
|
let mut options = fs::OpenOptions::new();
|
|
options.write(true).create(true).truncate(true);
|
|
|
|
#[cfg(unix)]
|
|
{
|
|
options.mode(0o755); // Read & execute for all, write for owner
|
|
}
|
|
|
|
let mut file = options.open(path).await?;
|
|
file.write_all(bytes.as_ref()).await?;
|
|
|
|
Ok(())
|
|
}
|