Support Intel macOS with the last upstream runtime.
Some checks failed
Tagged release / prepare-release (push) Successful in 3m0s
Tagged release / build-linux-x64 (push) Successful in 35m32s
Tagged release / build-macos (push) Failing after 38m56s
Tagged release / build-windows (push) Has been cancelled
Tagged release / publish-release (push) Has been cancelled
Tagged release / build-linux-arm64 (push) Has been cancelled
Some checks failed
Tagged release / prepare-release (push) Successful in 3m0s
Tagged release / build-linux-x64 (push) Successful in 35m32s
Tagged release / build-macos (push) Failing after 38m56s
Tagged release / build-windows (push) Has been cancelled
Tagged release / publish-release (push) Has been cancelled
Tagged release / build-linux-arm64 (push) Has been cancelled
This commit is contained in:
@@ -11,6 +11,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
[command, directory] if command == "macos-linker-alias" => {
|
||||
packaging::prepare_macos_linker_alias(Path::new(directory))
|
||||
}
|
||||
[command, directory] if command == "macos-x64-runtime" => {
|
||||
packaging::prepare_macos_x64_runtime(Path::new(directory))
|
||||
}
|
||||
[command, directory, sdk_libraries] if command == "windows-runtime" => {
|
||||
packaging::prepare_windows_runtime(Path::new(directory), Path::new(sdk_libraries))
|
||||
}
|
||||
@@ -42,7 +45,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
gitea::upload(assets.iter().map(|path| path.as_path()))
|
||||
}
|
||||
_ => Err(
|
||||
"usage: bds-release prepare|publish|macos-linker-alias <directory>|windows-runtime <directory> <sdk-libraries>|upload <asset>...|package <tag> <release-dir> <rust-lib-dir> <platform> <dist-dir> [--upload]"
|
||||
"usage: bds-release prepare|publish|macos-linker-alias <directory>|macos-x64-runtime <directory>|windows-runtime <directory> <sdk-libraries>|upload <asset>...|package <tag> <release-dir> <rust-lib-dir> <platform> <dist-dir> [--upload]"
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ const LC_LAZY_LOAD_DYLIB: u32 = 0x20;
|
||||
const LC_LOAD_UPWARD_DYLIB: u32 = 0x8000_0023;
|
||||
const DIRECTML_VERSION: &str = "1.15.4";
|
||||
const DIRECTML_SHA256: &str = "4e7cb7ddce8cf837a7a75dc029209b520ca0101470fcdf275c1f49736a3615b9";
|
||||
const MACOS_X64_ORT_VERSION: &str = "1.23.2";
|
||||
const MACOS_X64_ORT_SHA256: &str =
|
||||
"d10359e16347b57d9959f7e80a225a5b4a66ed7d7e007274a15cae86836485a6";
|
||||
|
||||
pub(crate) fn prepare_macos_linker_alias(directory: &Path) -> Result<(), Box<dyn Error>> {
|
||||
fs::create_dir_all(directory)?;
|
||||
@@ -33,6 +36,72 @@ pub(crate) fn prepare_macos_linker_alias(directory: &Path) -> Result<(), Box<dyn
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_macos_x64_runtime(directory: &Path) -> Result<(), Box<dyn Error>> {
|
||||
fs::create_dir_all(directory)?;
|
||||
let archive_path = directory.join(format!(
|
||||
"onnxruntime-osx-x86_64-{MACOS_X64_ORT_VERSION}.tgz"
|
||||
));
|
||||
let result = (|| {
|
||||
let url = format!(
|
||||
"https://github.com/microsoft/onnxruntime/releases/download/v{MACOS_X64_ORT_VERSION}/onnxruntime-osx-x86_64-{MACOS_X64_ORT_VERSION}.tgz"
|
||||
);
|
||||
let mut response = reqwest::blocking::get(url)?.error_for_status()?;
|
||||
let mut archive = File::create(&archive_path)?;
|
||||
io::copy(&mut response, &mut archive)?;
|
||||
drop(archive);
|
||||
|
||||
let mut archive = BufReader::new(File::open(&archive_path)?);
|
||||
let mut digest = Sha256::new();
|
||||
let mut buffer = [0_u8; 64 * 1024];
|
||||
loop {
|
||||
let read = archive.read(&mut buffer)?;
|
||||
if read == 0 {
|
||||
break;
|
||||
}
|
||||
digest.update(&buffer[..read]);
|
||||
}
|
||||
if format!("{:x}", digest.finalize()) != MACOS_X64_ORT_SHA256 {
|
||||
return Err("macOS x64 ONNX Runtime archive checksum mismatch".into());
|
||||
}
|
||||
|
||||
prepare_macos_x64_runtime_from_archive(File::open(&archive_path)?, directory)
|
||||
})();
|
||||
if archive_path.try_exists()? {
|
||||
fs::remove_file(archive_path)?;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn prepare_macos_x64_runtime_from_archive(
|
||||
archive: impl Read,
|
||||
directory: &Path,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
fs::create_dir_all(directory)?;
|
||||
let decoder = flate2::read::GzDecoder::new(archive);
|
||||
let mut archive = tar::Archive::new(decoder);
|
||||
for entry in archive.entries()? {
|
||||
let mut entry = entry?;
|
||||
let path = entry.path()?;
|
||||
let destination = if path.ends_with(format!(
|
||||
"lib/libonnxruntime.{MACOS_X64_ORT_VERSION}.dylib"
|
||||
)) {
|
||||
Some(format!("libonnxruntime.{MACOS_X64_ORT_VERSION}.dylib"))
|
||||
} else if path.ends_with("LICENSE") {
|
||||
Some("ONNXRuntime-LICENSE.txt".to_owned())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(destination) = destination {
|
||||
io::copy(&mut entry, &mut File::create(directory.join(destination))?)?;
|
||||
}
|
||||
}
|
||||
let versioned = directory.join(format!("libonnxruntime.{MACOS_X64_ORT_VERSION}.dylib"));
|
||||
require_file(&versioned)?;
|
||||
require_file(&directory.join("ONNXRuntime-LICENSE.txt"))?;
|
||||
fs::copy(versioned, directory.join("libonnxruntime.dylib"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_windows_runtime(
|
||||
directory: &Path,
|
||||
sdk_libraries: &Path,
|
||||
@@ -259,12 +328,24 @@ fn runtime_files(
|
||||
files.push((path, name));
|
||||
}
|
||||
let mut external_names = match platform {
|
||||
Platform::MacOs => fs::read_dir(release_dir)?
|
||||
.filter_map(Result::ok)
|
||||
.map(|entry| entry.file_name())
|
||||
.filter_map(|name| name.into_string().ok())
|
||||
.filter(|name| name.starts_with("libonnxruntime") && name.contains(".dylib"))
|
||||
.collect::<Vec<_>>(),
|
||||
Platform::MacOs => {
|
||||
let mut names = fs::read_dir(release_dir)?
|
||||
.filter_map(Result::ok)
|
||||
.map(|entry| entry.file_name())
|
||||
.filter_map(|name| name.into_string().ok())
|
||||
.filter(|name| name.starts_with("libonnxruntime") && name.contains(".dylib"))
|
||||
.collect::<Vec<_>>();
|
||||
let has_versioned = names
|
||||
.iter()
|
||||
.any(|name| name != "libonnxruntime.dylib");
|
||||
if has_versioned {
|
||||
names.retain(|name| name != "libonnxruntime.dylib");
|
||||
}
|
||||
if release_dir.join("ONNXRuntime-LICENSE.txt").is_file() {
|
||||
names.push("ONNXRuntime-LICENSE.txt".to_owned());
|
||||
}
|
||||
names
|
||||
}
|
||||
Platform::Linux => fs::read_dir(release_dir)?
|
||||
.filter_map(Result::ok)
|
||||
.map(|entry| entry.file_name())
|
||||
@@ -362,7 +443,7 @@ fn macos_dmg<'a>(
|
||||
|
||||
for (source, name) in &files {
|
||||
let entry = FileEntry::new_from_path(source, true);
|
||||
if name.ends_with(".dylib") {
|
||||
if is_macos_bundle_resource(name) {
|
||||
bundle.add_file_resources(name, entry)?;
|
||||
} else {
|
||||
bundle.add_file_macos(name, entry)?;
|
||||
@@ -375,12 +456,14 @@ fn macos_dmg<'a>(
|
||||
.map(|(_, name)| name.clone())
|
||||
.collect::<Vec<_>>();
|
||||
for (_, name) in &files {
|
||||
let staged = if name.ends_with(".dylib") {
|
||||
let staged = if is_macos_bundle_resource(name) {
|
||||
materialized.join("Contents/Resources").join(name)
|
||||
} else {
|
||||
materialized.join("Contents/MacOS").join(name)
|
||||
};
|
||||
rewrite_macho_rpaths(&staged, &runtime_names)?;
|
||||
if is_macos_macho(name) {
|
||||
rewrite_macho_rpaths(&staged, &runtime_names)?;
|
||||
}
|
||||
}
|
||||
let signer = UnifiedSigner::new(SigningSettings::default());
|
||||
signer.sign_path_in_place(&materialized)?;
|
||||
@@ -395,6 +478,14 @@ fn macos_dmg<'a>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_macos_bundle_resource(name: &str) -> bool {
|
||||
name.ends_with(".dylib") || name.ends_with(".txt")
|
||||
}
|
||||
|
||||
fn is_macos_macho(name: &str) -> bool {
|
||||
!name.ends_with(".txt")
|
||||
}
|
||||
|
||||
fn rewrite_macho_rpaths(path: &Path, runtime_names: &[String]) -> Result<(), Box<dyn Error>> {
|
||||
let mut bytes = fs::read(path)?;
|
||||
if read_u32(&bytes, 0)? != 0xfeed_facf {
|
||||
@@ -582,6 +673,88 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macos_x64_runtime_extracts_the_versioned_library_and_license() {
|
||||
let temp = tempdir().unwrap();
|
||||
let runtime = temp.path().join("runtime");
|
||||
let archive = Vec::new();
|
||||
let encoder = GzEncoder::new(archive, Compression::default());
|
||||
let mut archive = tar::Builder::new(encoder);
|
||||
for (name, contents) in [
|
||||
(
|
||||
"onnxruntime-osx-x86_64-1.23.2/lib/libonnxruntime.1.23.2.dylib",
|
||||
b"runtime".as_slice(),
|
||||
),
|
||||
(
|
||||
"onnxruntime-osx-x86_64-1.23.2/LICENSE",
|
||||
b"license".as_slice(),
|
||||
),
|
||||
(
|
||||
"onnxruntime-osx-x86_64-1.23.2/include/onnxruntime.h",
|
||||
b"header".as_slice(),
|
||||
),
|
||||
] {
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_size(contents.len() as u64);
|
||||
header.set_mode(0o644);
|
||||
header.set_cksum();
|
||||
archive.append_data(&mut header, name, contents).unwrap();
|
||||
}
|
||||
let encoder = archive.into_inner().unwrap();
|
||||
let archive = std::io::Cursor::new(encoder.finish().unwrap());
|
||||
|
||||
prepare_macos_x64_runtime_from_archive(archive, &runtime).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
fs::read(runtime.join("libonnxruntime.1.23.2.dylib")).unwrap(),
|
||||
b"runtime"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read(runtime.join("libonnxruntime.dylib")).unwrap(),
|
||||
b"runtime"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read(runtime.join("ONNXRuntime-LICENSE.txt")).unwrap(),
|
||||
b"license"
|
||||
);
|
||||
assert_eq!(fs::read_dir(runtime).unwrap().count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macos_runtime_files_package_one_versioned_ort_library_and_its_license() {
|
||||
let temp = tempdir().unwrap();
|
||||
let release = temp.path().join("release");
|
||||
let rust_libs = temp.path().join("rust-libs");
|
||||
fs::create_dir(&release).unwrap();
|
||||
fs::create_dir(&rust_libs).unwrap();
|
||||
for file in [
|
||||
"libbds_core.dylib",
|
||||
"libbds_server.dylib",
|
||||
"libonnxruntime.dylib",
|
||||
"libonnxruntime.1.23.2.dylib",
|
||||
"ONNXRuntime-LICENSE.txt",
|
||||
] {
|
||||
fs::write(release.join(file), file).unwrap();
|
||||
}
|
||||
|
||||
let files = runtime_files(Platform::MacOs, &release, &rust_libs).unwrap();
|
||||
let names = files.into_iter().map(|(_, name)| name).collect::<Vec<_>>();
|
||||
|
||||
assert!(names.contains(&"libonnxruntime.1.23.2.dylib".to_owned()));
|
||||
assert!(names.contains(&"ONNXRuntime-LICENSE.txt".to_owned()));
|
||||
assert!(!names.contains(&"libonnxruntime.dylib".to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macos_license_is_a_non_macho_bundle_resource() {
|
||||
assert!(is_macos_bundle_resource("ONNXRuntime-LICENSE.txt"));
|
||||
assert!(!is_macos_macho("ONNXRuntime-LICENSE.txt"));
|
||||
assert!(is_macos_bundle_resource("libonnxruntime.1.23.2.dylib"));
|
||||
assert!(is_macos_macho("libonnxruntime.1.23.2.dylib"));
|
||||
assert!(!is_macos_bundle_resource("bds-ui"));
|
||||
assert!(is_macos_macho("bds-ui"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_runtime_extracts_only_redistributable_files() {
|
||||
let temp = tempdir().unwrap();
|
||||
|
||||
@@ -46,6 +46,7 @@ fn desktop_packages_have_native_icons_and_cargo_commands() {
|
||||
}
|
||||
assert!(cargo_config.contains("prefer-dynamic"));
|
||||
assert!(cargo_config.contains("-mmacosx-version-min=26.0"));
|
||||
assert!(cargo_config.contains("link-arg=-Wl,-rpath,@executable_path\","));
|
||||
assert!(cargo_config.contains("@executable_path/../Resources"));
|
||||
assert!(cargo_config.contains("$ORIGIN:$ORIGIN/../lib/bds-ui"));
|
||||
|
||||
@@ -129,7 +130,11 @@ fn tagged_releases_are_built_and_packaged_with_rust_tools() {
|
||||
"runs-on: linux-arm64",
|
||||
"cargo-zigbuild",
|
||||
"macos-linker-alias",
|
||||
"macos-x64-runtime",
|
||||
"ORT_LIB_PATH",
|
||||
"ORT_PREFER_DYNAMIC_LINK",
|
||||
"-Lnative=target/macos-linker",
|
||||
"-Wl,-rpath,@executable_path ",
|
||||
"-Wl,-undefined,dynamic_lookup",
|
||||
"aarch64-apple-darwin",
|
||||
"x86_64-apple-darwin",
|
||||
|
||||
Reference in New Issue
Block a user