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:
Viktor Zoutman 2021-03-05 17:47:52 +01:00 committed by GitHub
parent a57891a3bc
commit 2a07fd3c8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 345 additions and 48 deletions

View file

@ -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

Binary file not shown.

View file

@ -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")
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")
.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");
};
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);
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()
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()
));
pb
};
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("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);
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("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

Binary file not shown.

View 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 => "",
}
}
}

View 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
View 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)?)
}
}