mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-08-03 06:40:21 +00:00
Add support for zip packaging, only on Windows for now
This commit is contained in:
parent
5d5f7cca75
commit
954a225a86
7 changed files with 155 additions and 109 deletions
|
@ -58,4 +58,4 @@ opt-level = 3
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[profile.dev.package.xtask]
|
[profile.dev.package.xtask]
|
||||||
opt-level = 3
|
opt-level = 2
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
[config]
|
|
||||||
default_to_workspace = false
|
|
||||||
skip_core_tasks = true
|
|
||||||
|
|
||||||
[tasks.build]
|
|
||||||
run_task = [
|
|
||||||
{ name = "build-windows", condition = { platforms = ["windows"] } },
|
|
||||||
{ name = "build-linux", condition = { platforms = ["linux"] } },
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.build-windows]
|
|
||||||
command = "cargo"
|
|
||||||
args = [
|
|
||||||
"build",
|
|
||||||
"-p", "offline_compiler",
|
|
||||||
"-p", "zluda_dump",
|
|
||||||
"-p", "zluda_inject",
|
|
||||||
"-p", "zluda_lib",
|
|
||||||
"-p", "zluda_ml",
|
|
||||||
"-p", "zluda_redirect",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.build-linux]
|
|
||||||
command = "cargo"
|
|
||||||
args = [
|
|
||||||
"build",
|
|
||||||
"-p", "offline_compiler",
|
|
||||||
"-p", "zluda_blas",
|
|
||||||
"-p", "zluda_blaslt",
|
|
||||||
"-p", "zluda_ccl",
|
|
||||||
"-p", "zluda_dnn",
|
|
||||||
"-p", "zluda_dump",
|
|
||||||
"-p", "zluda_fft",
|
|
||||||
"-p", "zluda_lib",
|
|
||||||
"-p", "zluda_ml",
|
|
||||||
"-p", "zluda_sparse",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.build-release]
|
|
||||||
command = "cargo"
|
|
||||||
args = [
|
|
||||||
"build",
|
|
||||||
"--release",
|
|
||||||
"-p", "offline_compiler",
|
|
||||||
"-p", "zluda_blas",
|
|
||||||
"-p", "zluda_blaslt",
|
|
||||||
"-p", "zluda_ccl",
|
|
||||||
"-p", "zluda_dnn",
|
|
||||||
"-p", "zluda_dump",
|
|
||||||
"-p", "zluda_fft",
|
|
||||||
"-p", "zluda_lib",
|
|
||||||
"-p", "zluda_ml",
|
|
||||||
"-p", "zluda_sparse",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.default]
|
|
||||||
alias = "build"
|
|
|
@ -18,3 +18,4 @@ features = [
|
||||||
|
|
||||||
[package.metadata.zluda]
|
[package.metadata.zluda]
|
||||||
debug_only = true
|
debug_only = true
|
||||||
|
skip_zip = true
|
||||||
|
|
|
@ -11,4 +11,7 @@ cargo_metadata = "=0.17.0"
|
||||||
# cargo-platform is a cargo_metadata, version 0.1.6 requires rust 1.70 or higher
|
# cargo-platform is a cargo_metadata, version 0.1.6 requires rust 1.70 or higher
|
||||||
cargo-platform = "=0.1.5"
|
cargo-platform = "=0.1.5"
|
||||||
serde = "1.0.193"
|
serde = "1.0.193"
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
|
flate2 = { version = "1.0.28", features = ["cloudflare_zlib"], default-features = false }
|
||||||
|
zip = { version = "0.6.6", features = ["deflate", "time"], default-features = false }
|
||||||
|
time = { version = "=0.3.23", features = ["local-offset"] }
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use argh::{EarlyExit, FromArgs, TopLevelCommand};
|
use argh::{EarlyExit, FromArgs, TopLevelCommand};
|
||||||
|
use cargo_metadata::camino::Utf8PathBuf;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
env,
|
env,
|
||||||
|
fs::File,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::Command,
|
||||||
};
|
};
|
||||||
|
@ -60,7 +63,7 @@ struct BuildCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromArgs)]
|
#[derive(FromArgs)]
|
||||||
/// Package build artifacts into an archive (.zip or .tar.gz)
|
/// Compile ZLUDA and package binaries into an archive (.zip or .tar.gz)
|
||||||
#[argh(subcommand, name = "zip")]
|
#[argh(subcommand, name = "zip")]
|
||||||
struct ZipCommand {
|
struct ZipCommand {
|
||||||
/// use artifacts from release mode
|
/// use artifacts from release mode
|
||||||
|
@ -73,10 +76,15 @@ fn main() -> Result<(), DynError> {
|
||||||
let args: Arguments = argh::from_env();
|
let args: Arguments = argh::from_env();
|
||||||
std::process::exit(match args.command {
|
std::process::exit(match args.command {
|
||||||
Subcommand::Build(BuildCommand { release }) => build(!release)?,
|
Subcommand::Build(BuildCommand { release }) => build(!release)?,
|
||||||
Subcommand::Zip(_) => panic!(),
|
Subcommand::Zip(ZipCommand { release }) => build_and_zip(!release)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_and_zip(is_debug: bool) -> Result<i32, DynError> {
|
||||||
|
let workspace = build_impl(is_debug)?;
|
||||||
|
zip(workspace)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ZludaMetadata {
|
struct ZludaMetadata {
|
||||||
zluda: Project,
|
zluda: Project,
|
||||||
|
@ -92,8 +100,6 @@ struct Project {
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
kind: TargetKind,
|
kind: TargetKind,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
top_level: bool,
|
|
||||||
#[serde(default)]
|
|
||||||
windows_only: bool,
|
windows_only: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
linux_only: bool,
|
linux_only: bool,
|
||||||
|
@ -104,6 +110,8 @@ struct Project {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
skip_dump_link: bool,
|
skip_dump_link: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
skip_zip: bool,
|
||||||
|
#[serde(default)]
|
||||||
linux_names: Vec<String>,
|
linux_names: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
dump_names: Vec<String>,
|
dump_names: Vec<String>,
|
||||||
|
@ -116,14 +124,56 @@ enum TargetKind {
|
||||||
Cdylib,
|
Cdylib,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Workspace {
|
||||||
|
pub cargo: String,
|
||||||
|
pub project_root: PathBuf,
|
||||||
|
pub projects: Vec<Project>,
|
||||||
|
pub target_directory: Utf8PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Workspace {
|
||||||
|
fn open(is_debug: bool) -> Result<Self, DynError> {
|
||||||
|
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
|
||||||
|
let project_root = Self::project_root()?;
|
||||||
|
let mut cmd = cargo_metadata::MetadataCommand::new();
|
||||||
|
cmd.cargo_path(&cargo).current_dir(&project_root).no_deps();
|
||||||
|
let cargo_metadata = cmd.exec()?;
|
||||||
|
let projects = cargo_metadata
|
||||||
|
.packages
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Project::new)
|
||||||
|
.filter(|p| !p.skip_build(is_debug))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut target_directory = cargo_metadata.target_directory;
|
||||||
|
target_directory.push(if is_debug { "debug" } else { "release" });
|
||||||
|
Ok(Workspace {
|
||||||
|
cargo,
|
||||||
|
project_root,
|
||||||
|
projects,
|
||||||
|
target_directory,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn project_root() -> Result<PathBuf, DynError> {
|
||||||
|
Ok(Path::new(&env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.ancestors()
|
||||||
|
.nth(1)
|
||||||
|
.ok_or::<DynError>("CARGO_MANIFEST_DIR".into())?
|
||||||
|
.to_path_buf())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cargo_command(&self) -> Command {
|
||||||
|
let mut command = Command::new(&self.cargo);
|
||||||
|
command.current_dir(&self.project_root);
|
||||||
|
command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
fn new(json_pkg: cargo_metadata::Package) -> Self {
|
fn new(json_pkg: cargo_metadata::Package) -> Option<Self> {
|
||||||
let mut project = serde_json::from_value::<Option<ZludaMetadata>>(json_pkg.metadata)
|
let project_metadata =
|
||||||
.unwrap()
|
serde_json::from_value::<Option<ZludaMetadata>>(json_pkg.metadata).unwrap()?;
|
||||||
.map_or(Default::default(), |x| x.zluda);
|
let mut project = project_metadata.zluda;
|
||||||
if project != Default::default() {
|
|
||||||
project.top_level = true;
|
|
||||||
}
|
|
||||||
project.name = json_pkg.name;
|
project.name = json_pkg.name;
|
||||||
if let Some((target_name, kind)) = json_pkg.targets.into_iter().find_map(|t| {
|
if let Some((target_name, kind)) = json_pkg.targets.into_iter().find_map(|t| {
|
||||||
match t.kind.first().map(std::ops::Deref::deref) {
|
match t.kind.first().map(std::ops::Deref::deref) {
|
||||||
|
@ -135,13 +185,10 @@ impl Project {
|
||||||
project.target_name = target_name;
|
project.target_name = target_name;
|
||||||
project.kind = kind;
|
project.kind = kind;
|
||||||
}
|
}
|
||||||
project
|
Some(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_build(&self, is_debug: bool) -> bool {
|
fn skip_build(&self, is_debug: bool) -> bool {
|
||||||
if !self.top_level {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if self.broken {
|
if self.broken {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -159,49 +206,93 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(is_debug: bool) -> Result<i32, DynError> {
|
fn build(is_debug: bool) -> Result<i32, DynError> {
|
||||||
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
|
build_impl(is_debug)?;
|
||||||
let project_root = project_root()?;
|
Ok(0)
|
||||||
let mut cmd = cargo_metadata::MetadataCommand::new();
|
}
|
||||||
cmd.cargo_path(&cargo).current_dir(&project_root).no_deps();
|
|
||||||
let metadata = cmd.exec()?;
|
fn build_impl(is_debug: bool) -> Result<Workspace, DynError> {
|
||||||
let projects = metadata
|
let workspace = Workspace::open(is_debug)?;
|
||||||
.packages
|
let mut command = workspace.cargo_command();
|
||||||
.into_iter()
|
command.arg("build");
|
||||||
.map(Project::new)
|
workspace
|
||||||
.filter(|p| !p.skip_build(is_debug))
|
.projects
|
||||||
.collect::<Vec<_>>();
|
.iter()
|
||||||
let mut command = Command::new(&cargo);
|
.fold(&mut command, |command, proj| {
|
||||||
command.current_dir(&project_root).arg("build");
|
command.args(["-p", &proj.name])
|
||||||
projects.iter().fold(&mut command, |command, proj| {
|
});
|
||||||
command.args(["-p", &proj.name])
|
|
||||||
});
|
|
||||||
if !is_debug {
|
if !is_debug {
|
||||||
command.arg("--release");
|
command.arg("--release");
|
||||||
}
|
}
|
||||||
let build_result = command.status()?.code().unwrap();
|
let build_result = command.status()?.code().unwrap();
|
||||||
if build_result != 0 {
|
if build_result != 0 {
|
||||||
return Ok(build_result);
|
return Err(format!("{command:?} failed with exit code {build_result}").into());
|
||||||
}
|
}
|
||||||
os::create_dump_dir_and_symlinks(is_debug, metadata.target_directory, projects);
|
os::create_dump_dir_and_symlinks(is_debug, &workspace);
|
||||||
|
Ok(workspace)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zip(workspace: Workspace) -> Result<i32, DynError> {
|
||||||
|
fn get_zip_entry_options(
|
||||||
|
f: &File,
|
||||||
|
time_offset: time::UtcOffset,
|
||||||
|
) -> Option<zip::write::FileOptions> {
|
||||||
|
let time = f.metadata().ok()?.modified().ok()?;
|
||||||
|
let time = time::OffsetDateTime::from(time).to_offset(time_offset);
|
||||||
|
Some(
|
||||||
|
zip::write::FileOptions::default()
|
||||||
|
.last_modified_time(zip::DateTime::try_from(time).ok()?),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let mut target_file = workspace.target_directory.clone();
|
||||||
|
target_file.push("zluda.zip");
|
||||||
|
let zip_archive = File::create(target_file)?;
|
||||||
|
let mut zip_writer = zip::write::ZipWriter::new(zip_archive);
|
||||||
|
let time_offset = time::UtcOffset::current_local_offset().unwrap_or(time::UtcOffset::UTC);
|
||||||
|
for p in workspace.projects {
|
||||||
|
if p.skip_zip {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut src_file = File::open(format!(
|
||||||
|
"{}/{}{}",
|
||||||
|
&workspace.target_directory,
|
||||||
|
p.target_name,
|
||||||
|
p.kind.suffix()
|
||||||
|
))?;
|
||||||
|
zip_writer.start_file(
|
||||||
|
format!("zluda/{}{}", p.target_name, p.kind.suffix()),
|
||||||
|
get_zip_entry_options(&src_file, time_offset)
|
||||||
|
.unwrap_or(zip::write::FileOptions::default()),
|
||||||
|
)?;
|
||||||
|
std::io::copy(&mut src_file, &mut zip_writer)?;
|
||||||
|
}
|
||||||
|
zip_writer.finish()?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_root() -> Result<PathBuf, DynError> {
|
impl TargetKind {
|
||||||
Ok(Path::new(&env!("CARGO_MANIFEST_DIR"))
|
#[cfg(unix)]
|
||||||
.ancestors()
|
fn prefix(self) -> &'static str {
|
||||||
.nth(1)
|
match self {
|
||||||
.ok_or::<DynError>("CARGO_MANIFEST_DIR".into())?
|
TargetKind::Binary => "",
|
||||||
.to_path_buf())
|
TargetKind::Cdylib => "lib",
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(unix)]
|
||||||
mod os {
|
fn suffix(self) -> &'static str {
|
||||||
use super::Project;
|
match self {
|
||||||
use cargo_metadata::camino::Utf8PathBuf;
|
TargetKind::Binary => "",
|
||||||
|
TargetKind::Cdylib => ".so",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This is 100% intentional, we don't want symlinks on Windows since
|
#[cfg(windows)]
|
||||||
// we use completely different scheme for injections here
|
fn suffix(self) -> &'static str {
|
||||||
pub(crate) fn create_dump_dir_and_symlinks(_: bool, _: Utf8PathBuf, _: Vec<Project>) {}
|
match self {
|
||||||
|
TargetKind::Binary => ".exe",
|
||||||
|
TargetKind::Cdylib => ".dll",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -211,11 +302,10 @@ mod os {
|
||||||
|
|
||||||
pub(crate) fn create_dump_dir_and_symlinks(
|
pub(crate) fn create_dump_dir_and_symlinks(
|
||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
mut target_directory: Utf8PathBuf,
|
mut target_directory: &Utf8PathBuf,
|
||||||
projects: Vec<Project>,
|
projects: Vec<Project>,
|
||||||
) {
|
) {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
target_directory.push(if is_debug { "debug" } else { "release" });
|
|
||||||
let mut dump_dir = target_directory.clone();
|
let mut dump_dir = target_directory.clone();
|
||||||
dump_dir.push("dump");
|
dump_dir.push("dump");
|
||||||
fs::create_dir_all(&dump_dir).unwrap();
|
fs::create_dir_all(&dump_dir).unwrap();
|
||||||
|
@ -279,3 +369,12 @@ mod os {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod os {
|
||||||
|
use crate::Workspace;
|
||||||
|
|
||||||
|
// This is 100% intentional, we don't want symlinks on Windows since
|
||||||
|
// we use a completely different scheme for injections there
|
||||||
|
pub(crate) fn create_dump_dir_and_symlinks(_: bool, _: &Workspace) {}
|
||||||
|
}
|
||||||
|
|
|
@ -26,3 +26,4 @@ features = [
|
||||||
[package.metadata.zluda]
|
[package.metadata.zluda]
|
||||||
debug_only = true
|
debug_only = true
|
||||||
windows_only = true
|
windows_only = true
|
||||||
|
skip_zip = true
|
||||||
|
|
|
@ -15,5 +15,4 @@ atiadlxx-sys = { path = "../atiadlxx-sys" }
|
||||||
rocm_smi-sys = { path = "../rocm_smi-sys" }
|
rocm_smi-sys = { path = "../rocm_smi-sys" }
|
||||||
|
|
||||||
[package.metadata.zluda]
|
[package.metadata.zluda]
|
||||||
top_level = true
|
|
||||||
linux_names = ["libnvidia-ml.so", "libnvidia-ml.so.1"]
|
linux_names = ["libnvidia-ml.so", "libnvidia-ml.so.1"]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue