Create symlinks, support custom profiles

This commit is contained in:
Andrzej Janik 2025-01-27 21:31:14 +00:00
parent c332858492
commit da173bb39a
4 changed files with 99 additions and 17 deletions

View file

@ -3,6 +3,17 @@ use cargo_metadata::{MetadataCommand, Package};
use serde::Deserialize; use serde::Deserialize;
use std::{env, ffi::OsString, process::Command}; use std::{env, ffi::OsString, process::Command};
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
enum Options {
#[bpaf(command)]
/// Compile ZLUDA (default command)
Build(#[bpaf(external(build))] Build),
#[bpaf(command)]
/// Build ZLUDA package
Zip,
}
#[derive(Debug, Clone, Bpaf)] #[derive(Debug, Clone, Bpaf)]
struct Build { struct Build {
#[bpaf(any("CARGO", not_help), many)] #[bpaf(any("CARGO", not_help), many)]
@ -18,15 +29,16 @@ fn not_help(s: OsString) -> Option<OsString> {
} }
} }
// We need to sniff out some args passed to cargo to understand how to create
// symlinks (should they go into `target/debug`, `target/release` or custom)
#[derive(Debug, Clone, Bpaf)] #[derive(Debug, Clone, Bpaf)]
#[bpaf(options)] struct Cargo {
enum Options { #[bpaf(switch, long, short)]
#[bpaf(command)] release: Option<bool>,
/// Compile ZLUDA (default command) #[bpaf(long)]
Build(#[bpaf(external(build))] Build), profile: Option<String>,
#[bpaf(command)] #[bpaf(any("", Some), many)]
/// Build ZLUDA package _unused: Vec<OsString>,
Zip,
} }
struct Project { struct Project {
@ -57,6 +69,8 @@ struct ZludaMetadata {
windows_only: bool, windows_only: bool,
#[serde(default)] #[serde(default)]
debug_only: bool, debug_only: bool,
#[serde(default)]
linux_symlinks: Vec<String>,
} }
fn main() { fn main() {
@ -77,30 +91,83 @@ fn main() {
} }
fn compile(b: Build) { fn compile(b: Build) {
let profile = sniff_out_profile_name(&b.cargo_arguments);
let meta = MetadataCommand::new().no_deps().exec().unwrap(); let meta = MetadataCommand::new().no_deps().exec().unwrap();
let is_release = b let target_directory = meta.target_directory.into_std_path_buf();
.cargo_arguments let projects = meta
.iter() .packages
.any(|a| a == "-r" || a == "--release"); .into_iter()
let projects = meta.packages.into_iter().filter_map(Project::try_new); .filter_map(Project::try_new)
.collect::<Vec<_>>();
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let mut command = Command::new(&cargo); let mut command = Command::new(&cargo);
command.arg("build"); command.arg("build");
command.arg("--locked"); command.arg("--locked");
for project in projects { for project in projects.iter() {
if project.meta.windows_only && cfg!(not(windows)) { if project.meta.windows_only && cfg!(not(windows)) {
continue; continue;
} }
if project.meta.debug_only && is_release { if project.meta.debug_only && profile != "debug" {
continue; continue;
} }
command.arg("--package"); command.arg("--package");
command.arg(&project.name); command.arg(&project.name);
} }
command.args(b.cargo_arguments); command.args(b.cargo_arguments);
command.status().unwrap(); assert!(command.status().unwrap().success());
os::make_symlinks(target_directory, projects, profile);
}
fn sniff_out_profile_name(b: &[OsString]) -> String {
let parsed_cargo_arguments = cargo().to_options().run_inner(b);
match parsed_cargo_arguments {
Ok(Cargo {
release: Some(true),
..
}) => "release".to_string(),
Ok(Cargo {
profile: Some(profile),
..
}) => profile,
_ => "debug".to_string(),
}
} }
fn zip() { fn zip() {
todo!() todo!()
} }
#[cfg(unix)]
mod os {
pub fn make_symlinks(
target_directory: std::path::PathBuf,
projects: Vec<super::Project>,
profile: String,
) {
use std::fs;
use std::os::unix::fs as unix_fs;
for project in projects.iter() {
let mut target = target_directory.clone();
target.extend([&*profile, &format!("lib{}.so", project.name)]);
for source in project.meta.linux_symlinks.iter() {
let mut link = target_directory.clone();
link.extend([&*profile, source]);
let mut dir = link.clone();
assert!(dir.pop());
fs::create_dir_all(dir).unwrap();
fs::remove_file(&link).ok();
unix_fs::symlink(&target, link).unwrap();
}
}
}
}
#[cfg(not(unix))]
mod os {
pub fn make_symlinks(
target_directory: std::path::PathBuf,
projects: Vec<super::Project>,
profile: String,
) {
}
}

View file

@ -26,3 +26,7 @@ rustc-hash = "1.1"
winapi = { version = "0.3", features = ["heapapi", "std"] } winapi = { version = "0.3", features = ["heapapi", "std"] }
[package.metadata.zluda] [package.metadata.zluda]
linux_symlinks = [
"libcuda.so",
"libcuda.so.1",
]

View file

@ -31,4 +31,9 @@ detours-sys = { path = "../detours-sys" }
libc = "0.2" libc = "0.2"
[package.metadata.zluda] [package.metadata.zluda]
debug_only = true linux_symlinks = [
"dump/libcuda.so",
"dump/libcuda.so.1",
"dump_nvidia/libcuda.so",
"dump_nvidia/libcuda.so.1",
]

View file

@ -13,3 +13,9 @@ cuda_base = { path = "../cuda_base" }
cuda_types = { path = "../cuda_types" } cuda_types = { path = "../cuda_types" }
[package.metadata.zluda] [package.metadata.zluda]
linux_symlinks = [
"libnvidia-ml.so",
"libnvidia-ml.so.1",
"dump/libnvidia-ml.so",
"dump/libnvidia-ml.so.1",
]