mirror of
https://github.com/italicsjenga/ash-molten.git
synced 2024-12-23 13:21:30 +11:00
Release 0.8.2+1.1.2#f28ab1c (#47)
* Squashed commits * Use a specific moltenvk commit indead * incremented version and no longer pulling * fixed version and prebuilt url * updated patch version
This commit is contained in:
parent
a57891a3bc
commit
2a07fd3c8a
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "ash-molten"
|
||||
description = "Statically linked MoltenVK for Vulkan on Mac using Ash"
|
||||
version = "0.7.2+1.1.0"
|
||||
version = "0.8.2+1.1.2-f28ab1c"
|
||||
authors = ["Embark <opensource@embark-studios.com>", "Maik Klein <maik.klein@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -11,10 +11,16 @@ categories = ["api-bindings", "rendering", "os::macos-apis"]
|
|||
repository = "https://github.com/EmbarkStudios/ash-molten"
|
||||
homepage = "https://github.com/EmbarkStudios/ash-molten"
|
||||
documentation = "https://docs.rs/ash-molten"
|
||||
build = "build/build.rs"
|
||||
|
||||
[dependencies]
|
||||
ash = "0.31"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
plist = { version = "1.0" }
|
||||
|
||||
[features]
|
||||
# Build features
|
||||
# Without build feature enabled MoltenVK will be build from source
|
||||
|
|
BIN
build/.DS_Store
vendored
Normal file
BIN
build/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -1,9 +1,22 @@
|
|||
mod xcframework;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
mod mac {
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
// MoltenVK git tagged release to use
|
||||
pub static VERSION: &str = "1.1.0";
|
||||
pub static MOLTEN_VK_VERSION: &str = "1.1.2";
|
||||
pub static MOLTEN_VK_PATCH: Option<&str> = Some("f28ab1c");
|
||||
|
||||
// Return the artifact tag in the form of "x.x.x" or if there is a patch specified "x.x.x#yyyyyyy"
|
||||
pub(crate) fn get_artifact_tag() -> String {
|
||||
if let Some(patch) = MOLTEN_VK_PATCH {
|
||||
format!("{}#{}", MOLTEN_VK_VERSION, patch)
|
||||
} else {
|
||||
MOLTEN_VK_VERSION.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
// Features are not used inside build scripts, so we have to explicitly query them from the
|
||||
// enviroment
|
||||
|
@ -31,7 +44,7 @@ mod mac {
|
|||
};
|
||||
|
||||
let checkout_dir = Path::new(&std::env::var("OUT_DIR").expect("Couldn't find OUT_DIR"))
|
||||
.join(format!("MoltenVK-{}", VERSION));
|
||||
.join(format!("MoltenVK-{}", get_artifact_tag()));
|
||||
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let wants_exit = exit.clone();
|
||||
|
@ -50,30 +63,49 @@ mod mac {
|
|||
}
|
||||
});
|
||||
|
||||
let git_status = if Path::new(&checkout_dir).exists() {
|
||||
Command::new("git")
|
||||
.current_dir(&checkout_dir)
|
||||
.arg("pull")
|
||||
.spawn()
|
||||
.expect("failed to spawn git")
|
||||
.wait()
|
||||
.expect("failed to pull MoltenVK")
|
||||
if Path::new(&checkout_dir).exists() {
|
||||
// Don't pull if a specific hash has been checkedout
|
||||
if MOLTEN_VK_PATCH.is_none() {
|
||||
let git_status = Command::new("git")
|
||||
.current_dir(&checkout_dir)
|
||||
.arg("pull")
|
||||
.spawn()
|
||||
.expect("failed to spawn git")
|
||||
.wait()
|
||||
.expect("failed to pull MoltenVK");
|
||||
|
||||
assert!(git_status.success(), "failed to get MoltenVK");
|
||||
}
|
||||
} else {
|
||||
Command::new("git")
|
||||
let branch = format!("v{}", MOLTEN_VK_VERSION.to_owned());
|
||||
let clone_args = if MOLTEN_VK_PATCH.is_none() {
|
||||
vec!["--branch", branch.as_str(), "--depth", "1"]
|
||||
} else {
|
||||
vec!["--single-branch", "--branch", "master"] // Can't specify depth if you switch to a different commit hash later.
|
||||
};
|
||||
let git_status = Command::new("git")
|
||||
.arg("clone")
|
||||
.arg("--branch")
|
||||
.arg(format!("v{}", VERSION.to_owned()))
|
||||
.arg("--depth")
|
||||
.arg("1")
|
||||
.args(clone_args)
|
||||
.arg("https://github.com/KhronosGroup/MoltenVK.git")
|
||||
.arg(&checkout_dir)
|
||||
.spawn()
|
||||
.expect("failed to spawn git")
|
||||
.wait()
|
||||
.expect("failed to clone MoltenVK")
|
||||
.expect("failed to clone MoltenVK");
|
||||
|
||||
assert!(git_status.success(), "failed to get MoltenVK");
|
||||
};
|
||||
|
||||
assert!(git_status.success(), "failed to get MoltenVK");
|
||||
if let Some(patch) = MOLTEN_VK_PATCH {
|
||||
let git_status = Command::new("git")
|
||||
.current_dir(&checkout_dir)
|
||||
.arg("checkout")
|
||||
.arg(patch)
|
||||
.status()
|
||||
.expect("failed to spawn git");
|
||||
|
||||
assert!(git_status.success(), "failed to checkout patch");
|
||||
}
|
||||
|
||||
// These (currently) match the identifiers used by moltenvk
|
||||
let (target_name, _dir) = match std::env::var("CARGO_CFG_TARGET_OS") {
|
||||
|
@ -124,7 +156,7 @@ mod mac {
|
|||
.arg("-s")
|
||||
.arg(format!(
|
||||
"https://api.github.com/repos/EmbarkStudios/ash-molten/releases/tags/MoltenVK-{}",
|
||||
VERSION
|
||||
get_artifact_tag().replace("#", "%23")
|
||||
))
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
|
@ -155,7 +187,7 @@ mod mac {
|
|||
.stdin(Stdio::from(cut_out))
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Couldn't launch cut");
|
||||
.expect("Couldn't launch tr");
|
||||
|
||||
let tr_out = tr.stdout.expect("Failed to open grep stdout");
|
||||
|
||||
|
@ -164,7 +196,7 @@ mod mac {
|
|||
.stdin(Stdio::from(tr_out))
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Couldn't launch cut")
|
||||
.expect("Couldn't launch xargs")
|
||||
.wait_with_output()
|
||||
.expect("failed to wait on xargs");
|
||||
|
||||
|
@ -191,59 +223,78 @@ mod mac {
|
|||
}
|
||||
}
|
||||
|
||||
use std::{
|
||||
collections::{hash_map::RandomState, HashMap},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
fn main() {
|
||||
use crate::mac::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// The 'external' feature was not enabled. Molten will be built automaticaly.
|
||||
let external_enabled = is_feature_enabled("EXTERNAL");
|
||||
let pre_built_enabled = is_feature_enabled("PRE_BUILT");
|
||||
|
||||
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
|
||||
assert!(
|
||||
!(external_enabled && pre_built_enabled),
|
||||
"external and prebuild cannot be active at the same time"
|
||||
);
|
||||
|
||||
if !external_enabled && !pre_built_enabled {
|
||||
let target_dir = Path::new(&std::env::var("OUT_DIR").unwrap())
|
||||
.join(format!("MoltenVK-{}", crate::mac::VERSION,));
|
||||
let _target_name = build_molten(&target_dir);
|
||||
if !external_enabled {
|
||||
let mut project_dir = if pre_built_enabled {
|
||||
let target_dir = Path::new(&std::env::var("OUT_DIR").unwrap()).join(format!(
|
||||
"Prebuilt-MoltenVK-{}",
|
||||
crate::mac::get_artifact_tag()
|
||||
));
|
||||
|
||||
download_prebuilt_molten(&target_dir);
|
||||
|
||||
let project_dir = {
|
||||
let mut pb = PathBuf::from(
|
||||
std::env::var("CARGO_MANIFEST_DIR").expect("unable to find env:CARGO_MANIFEST_DIR"),
|
||||
);
|
||||
pb.push(target_dir);
|
||||
pb.push(format!(
|
||||
"Package/Latest/MoltenVK/MoltenVK.xcframework/{}-{}",
|
||||
std::env::var("CARGO_CFG_TARGET_OS").unwrap(),
|
||||
std::env::var("CARGO_CFG_TARGET_ARCH").unwrap()
|
||||
));
|
||||
|
||||
pb.push("MoltenVK.xcframework");
|
||||
pb
|
||||
};
|
||||
} else {
|
||||
let target_dir = Path::new(&std::env::var("OUT_DIR").unwrap())
|
||||
.join(format!("MoltenVK-{}", crate::mac::get_artifact_tag()));
|
||||
let _target_name = build_molten(&target_dir);
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", project_dir.display());
|
||||
} else if pre_built_enabled {
|
||||
let target_dir = Path::new(&std::env::var("OUT_DIR").unwrap())
|
||||
.join(format!("Prebuilt-MoltenVK-{}", crate::mac::VERSION));
|
||||
|
||||
download_prebuilt_molten(&target_dir);
|
||||
|
||||
let project_dir = {
|
||||
let mut pb = PathBuf::from(
|
||||
std::env::var("CARGO_MANIFEST_DIR").expect("unable to find env:CARGO_MANIFEST_DIR"),
|
||||
);
|
||||
pb.push(target_dir);
|
||||
pb.push(format!(
|
||||
"{}-{}",
|
||||
std::env::var("CARGO_CFG_TARGET_OS").unwrap(),
|
||||
std::env::var("CARGO_CFG_TARGET_ARCH").unwrap()
|
||||
));
|
||||
pb.push("Package/Latest/MoltenVK/MoltenVK.xcframework");
|
||||
|
||||
pb
|
||||
};
|
||||
|
||||
let xcframework =
|
||||
xcframework::XcFramework::parse(&project_dir).expect("Failed to parse XCFramework");
|
||||
let native_libs = xcframework
|
||||
.AvailableLibraries
|
||||
.into_iter()
|
||||
.map(|lib| {
|
||||
lib.universal_to_native(project_dir.clone())
|
||||
.expect("Failed to get native library")
|
||||
})
|
||||
.flatten()
|
||||
.map(|lib| (lib.identifier(), lib.path()))
|
||||
.collect::<HashMap<xcframework::Identifier, PathBuf, RandomState>>();
|
||||
|
||||
let id = xcframework::Identifier::new(
|
||||
target_arch.into(),
|
||||
target_os.into(),
|
||||
xcframework::Variant::Default,
|
||||
);
|
||||
|
||||
let lib_path = native_libs.get(&id).expect("Library was not found");
|
||||
let lib_dir = lib_path.parent().unwrap();
|
||||
project_dir.push(lib_dir);
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", project_dir.display());
|
||||
}
|
||||
|
BIN
build/xcframework/.DS_Store
vendored
Normal file
BIN
build/xcframework/.DS_Store
vendored
Normal file
Binary file not shown.
96
build/xcframework/common.rs
Normal file
96
build/xcframework/common.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(into = "&'static str")]
|
||||
#[serde(from = "String")]
|
||||
pub enum Arch {
|
||||
X86,
|
||||
Amd64,
|
||||
Arm64,
|
||||
Arm64e,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(into = "&'static str")]
|
||||
#[serde(from = "String")]
|
||||
pub enum Platform {
|
||||
MacOS,
|
||||
IOS,
|
||||
TvOS,
|
||||
WatchOS,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(into = "&'static str")]
|
||||
#[serde(from = "String")]
|
||||
pub enum Variant {
|
||||
Default,
|
||||
Simulator,
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> From<T> for Arch {
|
||||
fn from(arch: T) -> Self {
|
||||
match arch.as_ref() {
|
||||
"x86_64" => Arch::Amd64,
|
||||
"x86" => Arch::X86,
|
||||
"arm64" => Arch::Arm64,
|
||||
"aarch64" => Arch::Arm64,
|
||||
"arm64e" => Arch::Arm64e,
|
||||
_ => Arch::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Arch> for &'a str {
|
||||
fn from(arch: Arch) -> Self {
|
||||
match arch {
|
||||
Arch::Amd64 => "x86_64",
|
||||
Arch::X86 => "x86",
|
||||
Arch::Arm64 => "arm64",
|
||||
Arch::Arm64e => "arm64e",
|
||||
Arch::Unknown => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> From<T> for Platform {
|
||||
fn from(platform: T) -> Self {
|
||||
match platform.as_ref() {
|
||||
"tvos" => Platform::TvOS,
|
||||
"macos" => Platform::MacOS,
|
||||
"ios" => Platform::IOS,
|
||||
"watchos" => Platform::WatchOS,
|
||||
_ => Platform::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Platform> for &'a str {
|
||||
fn from(platform: Platform) -> Self {
|
||||
match platform {
|
||||
Platform::TvOS => "tvos",
|
||||
Platform::MacOS => "macos",
|
||||
Platform::IOS => "ios",
|
||||
Platform::WatchOS => "watchos",
|
||||
Platform::Unknown => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> From<T> for Variant {
|
||||
fn from(variant: T) -> Self {
|
||||
match variant.as_ref() {
|
||||
"simulator" => Variant::Simulator,
|
||||
_ => Variant::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Variant> for &'a str {
|
||||
fn from(variant: Variant) -> Self {
|
||||
match variant {
|
||||
Variant::Simulator => "simulator",
|
||||
Variant::Default => "",
|
||||
}
|
||||
}
|
||||
}
|
121
build/xcframework/library.rs
Normal file
121
build/xcframework/library.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
use anyhow::Error;
|
||||
|
||||
use super::common::{Arch, Platform, Variant};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
string::String,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub struct Identifier {
|
||||
pub arch: Arch,
|
||||
pub platform: Platform,
|
||||
pub variant: Variant,
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
pub fn new(arch: Arch, platform: Platform, variant: Variant) -> Self {
|
||||
Self {
|
||||
arch,
|
||||
platform,
|
||||
variant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct UniversalLibrary {
|
||||
LibraryPath: String,
|
||||
SupportedArchitectures: Vec<Arch>,
|
||||
SupportedPlatformVariant: Option<Variant>,
|
||||
SupportedPlatform: Platform,
|
||||
LibraryIdentifier: String,
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug)]
|
||||
pub struct NativeLibrary {
|
||||
LibraryPath: String,
|
||||
SupportedArchitectures: Arch,
|
||||
SupportedPlatformVariant: Option<Variant>,
|
||||
SupportedPlatform: Platform,
|
||||
LibraryIdentifier: String,
|
||||
}
|
||||
|
||||
impl UniversalLibrary {
|
||||
pub fn universal_to_native<P: AsRef<Path>>(
|
||||
self,
|
||||
xcframework_dir: P,
|
||||
) -> Result<Vec<NativeLibrary>, Error> {
|
||||
let lib_id = &self.LibraryIdentifier;
|
||||
let platform = &self.SupportedPlatform;
|
||||
let variant = self.SupportedPlatformVariant.as_ref();
|
||||
let lib_path = &self.LibraryPath;
|
||||
|
||||
if self.SupportedArchitectures.len() == 1 {
|
||||
let arch = &self.SupportedArchitectures[0];
|
||||
Ok(vec![NativeLibrary {
|
||||
LibraryPath: lib_path.into(),
|
||||
SupportedArchitectures: *arch,
|
||||
SupportedPlatformVariant: variant.cloned(),
|
||||
SupportedPlatform: *platform,
|
||||
LibraryIdentifier: lib_id.into(),
|
||||
}])
|
||||
} else {
|
||||
let mut native_libs = Vec::new();
|
||||
let xcframework_dir = xcframework_dir.as_ref().to_path_buf();
|
||||
let full_path = xcframework_dir.join(lib_id).join(lib_path);
|
||||
|
||||
for arch in &self.SupportedArchitectures {
|
||||
let platform_str: &str = (*platform).into();
|
||||
let arch_str: &str = (*arch).into();
|
||||
let mut new_identifier = format!("{}-{}", platform_str, arch_str);
|
||||
|
||||
if let Some(variant) = variant {
|
||||
let variant_str: &str = (*variant).into();
|
||||
new_identifier.push_str(format!("-{}", variant_str).as_str());
|
||||
}
|
||||
|
||||
let mut out_path = xcframework_dir.join(new_identifier.clone());
|
||||
std::fs::create_dir_all(&out_path)?;
|
||||
out_path.push(&lib_path);
|
||||
|
||||
assert!(Command::new("lipo")
|
||||
.arg(&full_path)
|
||||
.arg("-thin")
|
||||
.arg(arch_str)
|
||||
.arg("-output")
|
||||
.arg(out_path)
|
||||
.status()
|
||||
.expect("Failed to spawn lipo")
|
||||
.success());
|
||||
|
||||
native_libs.push(NativeLibrary {
|
||||
LibraryPath: lib_path.into(),
|
||||
SupportedArchitectures: *arch,
|
||||
SupportedPlatformVariant: variant.copied(),
|
||||
SupportedPlatform: *platform,
|
||||
LibraryIdentifier: new_identifier,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(native_libs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeLibrary {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
Path::new(&format!("{}/{}", self.LibraryIdentifier, self.LibraryPath)).to_path_buf()
|
||||
}
|
||||
|
||||
pub fn identifier(&self) -> Identifier {
|
||||
Identifier::new(
|
||||
self.SupportedArchitectures,
|
||||
self.SupportedPlatform,
|
||||
self.SupportedPlatformVariant.unwrap_or(Variant::Default),
|
||||
)
|
||||
}
|
||||
}
|
23
build/xcframework/mod.rs
Normal file
23
build/xcframework/mod.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use anyhow::Error;
|
||||
use std::{fs::File, io::BufReader, path::Path};
|
||||
|
||||
mod common;
|
||||
mod library;
|
||||
|
||||
pub use common::*;
|
||||
pub use library::*;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct XcFramework {
|
||||
pub AvailableLibraries: Vec<library::UniversalLibrary>,
|
||||
pub CFBundlePackageType: String,
|
||||
pub XCFrameworkFormatVersion: String,
|
||||
}
|
||||
|
||||
impl XcFramework {
|
||||
pub fn parse<P: AsRef<Path>>(path: P) -> Result<XcFramework, Error> {
|
||||
let mut reader = BufReader::new(File::open(path.as_ref().join("Info.plist"))?);
|
||||
Ok(plist::from_reader(&mut reader)?)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue