mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-18 16:11:38 +03:00
feat(bundler): codesign nested code on macos (#8259)
* feat(bundler): codesign nested code on macos * chore: update changelog tag * typo * also sign stuff in the Libraries folder tested this for spacedrive, which has a bunch of dylib inside the libraries folder * Update .changes/mac-bundler-nested-code-sign.md [skip ci] --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
parent
8f8729d918
commit
89911296e4
6
.changes/mac-bundler-nested-code-sign.md
Normal file
6
.changes/mac-bundler-nested-code-sign.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:feat
|
||||
"tauri-bundler": patch:feat
|
||||
---
|
||||
|
||||
On macOS, support for signing nested .dylib, .app, .xpc and .framework under predefined directories inside the bundled frameworks ("MacOS", "Frameworks", "Plugins", "Helpers", "XPCServices" and "Libraries").
|
@ -39,6 +39,15 @@ use std::{
|
||||
process::Command,
|
||||
};
|
||||
|
||||
const NESTED_CODE_FOLDER: [&str; 6] = [
|
||||
"MacOS",
|
||||
"Frameworks",
|
||||
"Plugins",
|
||||
"Helpers",
|
||||
"XPCServices",
|
||||
"Libraries",
|
||||
];
|
||||
|
||||
/// Bundles the project.
|
||||
/// Returns a vector of PathBuf that shows where the .app was created.
|
||||
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
@ -77,18 +86,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
let framework_paths = copy_frameworks_to_bundle(&bundle_directory, settings)
|
||||
.with_context(|| "Failed to bundle frameworks")?;
|
||||
sign_paths.extend(
|
||||
framework_paths
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
let ext = p.extension();
|
||||
ext == Some(OsStr::new("framework")) || ext == Some(OsStr::new("dylib"))
|
||||
})
|
||||
.map(|path| SignTarget {
|
||||
path,
|
||||
is_an_executable: false,
|
||||
}),
|
||||
);
|
||||
sign_paths.extend(framework_paths);
|
||||
|
||||
settings.copy_resources(&resources_dir)?;
|
||||
|
||||
@ -141,7 +139,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
fn remove_extra_attr(app_bundle_path: &Path) -> crate::Result<()> {
|
||||
Command::new("xattr")
|
||||
.arg("-cr")
|
||||
.arg("-crs")
|
||||
.arg(app_bundle_path)
|
||||
.output_ok()
|
||||
.context("failed to remove extra attributes from app bundle")?;
|
||||
@ -265,7 +263,7 @@ fn copy_framework_from(dest_dir: &Path, framework: &str, src_dir: &Path) -> crat
|
||||
fn copy_frameworks_to_bundle(
|
||||
bundle_directory: &Path,
|
||||
settings: &Settings,
|
||||
) -> crate::Result<Vec<PathBuf>> {
|
||||
) -> crate::Result<Vec<SignTarget>> {
|
||||
let mut paths = Vec::new();
|
||||
|
||||
let frameworks = settings
|
||||
@ -288,7 +286,7 @@ fn copy_frameworks_to_bundle(
|
||||
.expect("Couldn't get framework filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_dir(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
add_framework_sign_path(&src_path, &dest_path, &mut paths);
|
||||
continue;
|
||||
} else if framework.ends_with(".dylib") {
|
||||
let src_path = PathBuf::from(framework);
|
||||
@ -301,7 +299,10 @@ fn copy_frameworks_to_bundle(
|
||||
let src_name = src_path.file_name().expect("Couldn't get library filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_file(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: false,
|
||||
});
|
||||
continue;
|
||||
} else if framework.contains('/') {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
@ -330,3 +331,90 @@ fn copy_frameworks_to_bundle(
|
||||
}
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
/// Recursively add framework's sign paths.
|
||||
/// If the framework has multiple versions, it will sign "Current" version by default.
|
||||
fn add_framework_sign_path(
|
||||
framework_root: &Path,
|
||||
dest_path: &Path,
|
||||
sign_paths: &mut Vec<SignTarget>,
|
||||
) {
|
||||
if framework_root.join("Versions/Current").exists() {
|
||||
add_nested_code_sign_path(
|
||||
&framework_root.join("Versions/Current"),
|
||||
&dest_path.join("Versions/Current"),
|
||||
sign_paths,
|
||||
);
|
||||
} else {
|
||||
add_nested_code_sign_path(framework_root, dest_path, sign_paths);
|
||||
}
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path.into(),
|
||||
is_an_executable: false,
|
||||
});
|
||||
}
|
||||
|
||||
/// Recursively add executable bundle's sign path (.xpc, .app).
|
||||
fn add_executable_bundle_sign_path(
|
||||
bundle_root: &Path,
|
||||
dest_path: &Path,
|
||||
sign_paths: &mut Vec<SignTarget>,
|
||||
) {
|
||||
if bundle_root.join("Contents").exists() {
|
||||
add_nested_code_sign_path(
|
||||
&bundle_root.join("Contents"),
|
||||
&dest_path.join("Contents"),
|
||||
sign_paths,
|
||||
);
|
||||
} else {
|
||||
add_nested_code_sign_path(bundle_root, dest_path, sign_paths);
|
||||
}
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path.into(),
|
||||
is_an_executable: true,
|
||||
});
|
||||
}
|
||||
|
||||
fn add_nested_code_sign_path(src_path: &Path, dest_path: &Path, sign_paths: &mut Vec<SignTarget>) {
|
||||
for folder_name in NESTED_CODE_FOLDER.iter() {
|
||||
let src_folder_path = src_path.join(folder_name);
|
||||
let dest_folder_path = dest_path.join(folder_name);
|
||||
|
||||
if src_folder_path.exists() {
|
||||
for entry in walkdir::WalkDir::new(src_folder_path)
|
||||
.min_depth(1)
|
||||
.max_depth(1)
|
||||
.into_iter()
|
||||
.filter_map(|e| e.ok())
|
||||
{
|
||||
if entry.path_is_symlink() || entry.file_name().to_string_lossy().starts_with('.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dest_path = dest_folder_path.join(entry.file_name());
|
||||
let ext = entry.path().extension();
|
||||
if entry.path().is_dir() {
|
||||
// Bundles, like .app, .framework, .xpc
|
||||
if ext == Some(OsStr::new("framework")) {
|
||||
add_framework_sign_path(&entry.clone().into_path(), &dest_path, sign_paths);
|
||||
} else if ext == Some(OsStr::new("xpc")) || ext == Some(OsStr::new("app")) {
|
||||
add_executable_bundle_sign_path(&entry.clone().into_path(), &dest_path, sign_paths);
|
||||
}
|
||||
} else if entry.path().is_file() {
|
||||
// Binaries, like .dylib, Mach-O executables
|
||||
if ext == Some(OsStr::new("dylib")) {
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: false,
|
||||
});
|
||||
} else if ext.is_none() {
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user