mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-03 10:11:15 +02:00
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
@@ -23,9 +23,9 @@
|
||||
// files into the `Contents` directory of the bundle.
|
||||
|
||||
use super::{
|
||||
super::common,
|
||||
super::common::{self, CommandExt},
|
||||
icon::create_icns_file,
|
||||
sign::{notarize, notarize_auth, sign},
|
||||
sign::{notarize, notarize_auth, sign, SignTarget},
|
||||
};
|
||||
use crate::Settings;
|
||||
|
||||
@@ -33,8 +33,10 @@ use anyhow::Context;
|
||||
use log::{info, warn};
|
||||
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
/// Bundles the project.
|
||||
@@ -65,6 +67,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
let resources_dir = bundle_directory.join("Resources");
|
||||
let bin_dir = bundle_directory.join("MacOS");
|
||||
let mut sign_paths = Vec::new();
|
||||
|
||||
let bundle_icon_file: Option<PathBuf> =
|
||||
{ create_icns_file(&resources_dir, settings).with_context(|| "Failed to create app icon")? };
|
||||
@@ -72,20 +75,52 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
create_info_plist(&bundle_directory, bundle_icon_file, settings)
|
||||
.with_context(|| "Failed to create Info.plist")?;
|
||||
|
||||
copy_frameworks_to_bundle(&bundle_directory, settings)
|
||||
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,
|
||||
}),
|
||||
);
|
||||
|
||||
settings.copy_resources(&resources_dir)?;
|
||||
|
||||
settings
|
||||
let bin_paths = settings
|
||||
.copy_binaries(&bin_dir)
|
||||
.with_context(|| "Failed to copy external binaries")?;
|
||||
sign_paths.extend(bin_paths.into_iter().map(|path| SignTarget {
|
||||
path,
|
||||
is_an_executable: true,
|
||||
}));
|
||||
|
||||
copy_binaries_to_bundle(&bundle_directory, settings)?;
|
||||
let bin_paths = copy_binaries_to_bundle(&bundle_directory, settings)?;
|
||||
sign_paths.extend(bin_paths.into_iter().map(|path| SignTarget {
|
||||
path,
|
||||
is_an_executable: true,
|
||||
}));
|
||||
|
||||
if let Some(identity) = &settings.macos().signing_identity {
|
||||
// Sign frameworks and sidecar binaries first, per apple, signing must be done inside out
|
||||
// https://developer.apple.com/forums/thread/701514
|
||||
sign_paths.push(SignTarget {
|
||||
path: app_bundle_path.clone(),
|
||||
is_an_executable: true,
|
||||
});
|
||||
|
||||
// Remove extra attributes, which could cause codesign to fail
|
||||
// https://developer.apple.com/library/archive/qa/qa1940/_index.html
|
||||
remove_extra_attr(&app_bundle_path)?;
|
||||
|
||||
// sign application
|
||||
sign(app_bundle_path.clone(), identity, settings, true)?;
|
||||
sign(sign_paths, identity, settings)?;
|
||||
|
||||
// notarization is required for distribution
|
||||
match notarize_auth() {
|
||||
Ok(auth) => {
|
||||
@@ -100,15 +135,30 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
Ok(vec![app_bundle_path])
|
||||
}
|
||||
|
||||
fn remove_extra_attr(app_bundle_path: &Path) -> crate::Result<()> {
|
||||
Command::new("xattr")
|
||||
.arg("-cr")
|
||||
.arg(app_bundle_path)
|
||||
.output_ok()
|
||||
.context("failed to remove extra attributes from app bundle")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Copies the app's binaries to the bundle.
|
||||
fn copy_binaries_to_bundle(bundle_directory: &Path, settings: &Settings) -> crate::Result<()> {
|
||||
fn copy_binaries_to_bundle(
|
||||
bundle_directory: &Path,
|
||||
settings: &Settings,
|
||||
) -> crate::Result<Vec<PathBuf>> {
|
||||
let mut paths = Vec::new();
|
||||
let dest_dir = bundle_directory.join("MacOS");
|
||||
for bin in settings.binaries() {
|
||||
let bin_path = settings.binary_path(bin);
|
||||
common::copy_file(&bin_path, &dest_dir.join(bin.name()))
|
||||
let dest_path = dest_dir.join(bin.name());
|
||||
common::copy_file(&bin_path, &dest_path)
|
||||
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
|
||||
paths.push(dest_path);
|
||||
}
|
||||
Ok(())
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
// Creates the Info.plist file.
|
||||
@@ -208,7 +258,12 @@ fn copy_framework_from(dest_dir: &Path, framework: &str, src_dir: &Path) -> crat
|
||||
}
|
||||
|
||||
// Copies the macOS application bundle frameworks to the .app
|
||||
fn copy_frameworks_to_bundle(bundle_directory: &Path, settings: &Settings) -> crate::Result<()> {
|
||||
fn copy_frameworks_to_bundle(
|
||||
bundle_directory: &Path,
|
||||
settings: &Settings,
|
||||
) -> crate::Result<Vec<PathBuf>> {
|
||||
let mut paths = Vec::new();
|
||||
|
||||
let frameworks = settings
|
||||
.macos()
|
||||
.frameworks
|
||||
@@ -216,7 +271,7 @@ fn copy_frameworks_to_bundle(bundle_directory: &Path, settings: &Settings) -> cr
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
if frameworks.is_empty() {
|
||||
return Ok(());
|
||||
return Ok(paths);
|
||||
}
|
||||
let dest_dir = bundle_directory.join("Frameworks");
|
||||
fs::create_dir_all(bundle_directory)
|
||||
@@ -227,7 +282,9 @@ fn copy_frameworks_to_bundle(bundle_directory: &Path, settings: &Settings) -> cr
|
||||
let src_name = src_path
|
||||
.file_name()
|
||||
.expect("Couldn't get framework filename");
|
||||
common::copy_dir(&src_path, &dest_dir.join(src_name))?;
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_dir(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
continue;
|
||||
} else if framework.ends_with(".dylib") {
|
||||
let src_path = PathBuf::from(framework);
|
||||
@@ -238,7 +295,9 @@ fn copy_frameworks_to_bundle(bundle_directory: &Path, settings: &Settings) -> cr
|
||||
)));
|
||||
}
|
||||
let src_name = src_path.file_name().expect("Couldn't get library filename");
|
||||
common::copy_file(&src_path, &dest_dir.join(src_name))?;
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_file(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
continue;
|
||||
} else if framework.contains('/') {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
@@ -265,5 +324,5 @@ fn copy_frameworks_to_bundle(bundle_directory: &Path, settings: &Settings) -> cr
|
||||
framework
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
@@ -153,7 +153,14 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
|
||||
|
||||
// Sign DMG if needed
|
||||
if let Some(identity) = &settings.macos().signing_identity {
|
||||
super::sign::sign(dmg_path.clone(), identity, settings, false)?;
|
||||
super::sign::sign(
|
||||
vec![super::sign::SignTarget {
|
||||
path: dmg_path.clone(),
|
||||
is_an_executable: false,
|
||||
}],
|
||||
identity,
|
||||
settings,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(Bundled {
|
||||
|
||||
@@ -144,13 +144,13 @@ pub fn delete_keychain() {
|
||||
.output_ok();
|
||||
}
|
||||
|
||||
pub fn sign(
|
||||
path_to_sign: PathBuf,
|
||||
identity: &str,
|
||||
settings: &Settings,
|
||||
is_an_executable: bool,
|
||||
) -> crate::Result<()> {
|
||||
info!(action = "Signing"; "{} with identity \"{}\"", path_to_sign.display(), identity);
|
||||
pub struct SignTarget {
|
||||
pub path: PathBuf,
|
||||
pub is_an_executable: bool,
|
||||
}
|
||||
|
||||
pub fn sign(targets: Vec<SignTarget>, identity: &str, settings: &Settings) -> crate::Result<()> {
|
||||
info!(action = "Signing"; "with identity \"{}\"", identity);
|
||||
|
||||
let setup_keychain = if let (Some(certificate_encoded), Some(certificate_password)) = (
|
||||
var_os("APPLE_CERTIFICATE"),
|
||||
@@ -164,20 +164,24 @@ pub fn sign(
|
||||
false
|
||||
};
|
||||
|
||||
let res = try_sign(
|
||||
path_to_sign,
|
||||
identity,
|
||||
settings,
|
||||
is_an_executable,
|
||||
setup_keychain,
|
||||
);
|
||||
info!("Signing app bundle...");
|
||||
|
||||
for target in targets {
|
||||
try_sign(
|
||||
target.path,
|
||||
identity,
|
||||
settings,
|
||||
target.is_an_executable,
|
||||
setup_keychain,
|
||||
)?;
|
||||
}
|
||||
|
||||
if setup_keychain {
|
||||
// delete the keychain again after signing
|
||||
delete_keychain();
|
||||
}
|
||||
|
||||
res
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_sign(
|
||||
@@ -187,6 +191,8 @@ fn try_sign(
|
||||
is_an_executable: bool,
|
||||
tauri_keychain: bool,
|
||||
) -> crate::Result<()> {
|
||||
info!(action = "Signing"; "{}", path_to_sign.display());
|
||||
|
||||
let mut args = vec!["--force", "-s", identity];
|
||||
|
||||
if tauri_keychain {
|
||||
@@ -205,13 +211,9 @@ fn try_sign(
|
||||
args.push("runtime");
|
||||
}
|
||||
|
||||
if path_to_sign.is_dir() {
|
||||
args.push("--deep");
|
||||
}
|
||||
|
||||
Command::new("codesign")
|
||||
.args(args)
|
||||
.arg(path_to_sign.to_string_lossy().to_string())
|
||||
.arg(path_to_sign)
|
||||
.output_ok()
|
||||
.context("failed to sign app")?;
|
||||
|
||||
@@ -260,7 +262,14 @@ pub fn notarize(
|
||||
|
||||
// sign the zip file
|
||||
if let Some(identity) = &settings.macos().signing_identity {
|
||||
sign(zip_path.clone(), identity, settings, false)?;
|
||||
sign(
|
||||
vec![SignTarget {
|
||||
path: zip_path.clone(),
|
||||
is_an_executable: false,
|
||||
}],
|
||||
identity,
|
||||
settings,
|
||||
)?;
|
||||
};
|
||||
|
||||
let notarize_args = vec![
|
||||
|
||||
@@ -761,7 +761,11 @@ impl Settings {
|
||||
}
|
||||
|
||||
/// Copies external binaries to a path.
|
||||
pub fn copy_binaries(&self, path: &Path) -> crate::Result<()> {
|
||||
///
|
||||
/// Returns the list of destination paths.
|
||||
pub fn copy_binaries(&self, path: &Path) -> crate::Result<Vec<PathBuf>> {
|
||||
let mut paths = Vec::new();
|
||||
|
||||
for src in self.external_binaries() {
|
||||
let src = src?;
|
||||
let dest = path.join(
|
||||
@@ -771,9 +775,10 @@ impl Settings {
|
||||
.to_string_lossy()
|
||||
.replace(&format!("-{}", self.target), ""),
|
||||
);
|
||||
common::copy_file(&src, dest)?;
|
||||
common::copy_file(&src, &dest)?;
|
||||
paths.push(dest);
|
||||
}
|
||||
Ok(())
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
/// Copies resources to a path.
|
||||
|
||||
Reference in New Issue
Block a user