@@ -20,7 +20,7 @@ use crate::{
2020#[ tracing:: instrument( level = "trace" , skip( ctx) ) ]
2121pub ( crate ) fn package ( ctx : & Context ) -> crate :: Result < Vec < PathBuf > > {
2222 let Context { config, .. } = ctx;
23- // we should use the bundle name (App name) as a MacOS standard.
23+ // we should use the bundle name (App name) as a macOS standard.
2424 // version or platform shouldn't be included in the App name.
2525 let app_product_name = format ! ( "{}.app" , config. product_name) ;
2626 let app_bundle_path = config. out_dir ( ) . join ( & app_product_name) ;
@@ -72,6 +72,12 @@ pub(crate) fn package(ctx: &Context) -> crate::Result<Vec<PathBuf>> {
7272 tracing:: debug!( "Copying resources" ) ;
7373 config. copy_resources ( & resources_dir) ?;
7474
75+ tracing:: debug!( "Copying embedded.provisionprofile" ) ;
76+ copy_embedded_provisionprofile_file ( & contents_directory, config) ?;
77+
78+ tracing:: debug!( "Copying embedded apps" ) ;
79+ let embedded_apps = copy_embedded_apps ( & contents_directory, config) ?;
80+
7581 tracing:: debug!( "Copying external binaries" ) ;
7682 config. copy_external_binaries ( & bin_dir) ?;
7783 tracing:: debug!( "Copying binaries" ) ;
@@ -90,7 +96,8 @@ pub(crate) fn package(ctx: &Context) -> crate::Result<Vec<PathBuf>> {
9096 let files = walkdir:: WalkDir :: new ( & app_bundle_path)
9197 . into_iter ( )
9298 . flatten ( )
93- . map ( |dir| dir. into_path ( ) ) ;
99+ . map ( |dir| dir. into_path ( ) )
100+ . filter ( |path| !embedded_apps. iter ( ) . any ( |x| path. starts_with ( x) ) ) ;
94101
95102 // Filter all files for Mach-O headers. This will target all .dylib and native executable files
96103 for file in files {
@@ -203,7 +210,7 @@ fn create_info_plist(
203210 plist. insert (
204211 "CFBundleIconFile" . into ( ) ,
205212 path. file_name ( )
206- . ok_or_else ( || crate :: Error :: FailedToExtractFilename ( path. clone ( ) ) ) ?
213+ . ok_or_else ( || Error :: FailedToExtractFilename ( path. clone ( ) ) ) ?
207214 . to_string_lossy ( )
208215 . into_owned ( )
209216 . into ( ) ,
@@ -349,18 +356,18 @@ fn create_info_plist(
349356#[ tracing:: instrument( level = "trace" ) ]
350357fn copy_dir ( from : & Path , to : & Path ) -> crate :: Result < ( ) > {
351358 if !from. exists ( ) {
352- return Err ( crate :: Error :: DoesNotExist ( from. to_path_buf ( ) ) ) ;
359+ return Err ( Error :: DoesNotExist ( from. to_path_buf ( ) ) ) ;
353360 }
354361 if !from. is_dir ( ) {
355- return Err ( crate :: Error :: IsNotDirectory ( from. to_path_buf ( ) ) ) ;
362+ return Err ( Error :: IsNotDirectory ( from. to_path_buf ( ) ) ) ;
356363 }
357364 if to. exists ( ) {
358- return Err ( crate :: Error :: AlreadyExists ( to. to_path_buf ( ) ) ) ;
365+ return Err ( Error :: AlreadyExists ( to. to_path_buf ( ) ) ) ;
359366 }
360367
361368 let parent = to
362369 . parent ( )
363- . ok_or_else ( || crate :: Error :: ParentDirNotFound ( to. to_path_buf ( ) ) ) ?;
370+ . ok_or_else ( || Error :: ParentDirNotFound ( to. to_path_buf ( ) ) ) ?;
364371 fs:: create_dir_all ( parent) . map_err ( |e| Error :: IoWithPath ( parent. to_path_buf ( ) , e) ) ?;
365372 for entry in walkdir:: WalkDir :: new ( from) {
366373 let entry = entry?;
@@ -425,27 +432,27 @@ fn copy_frameworks_to_bundle(
425432 let src_path = PathBuf :: from ( framework) ;
426433 let src_name = src_path
427434 . file_name ( )
428- . ok_or_else ( || crate :: Error :: FailedToExtractFilename ( src_path. clone ( ) ) ) ?;
435+ . ok_or_else ( || Error :: FailedToExtractFilename ( src_path. clone ( ) ) ) ?;
429436 let dest_path = dest_dir. join ( src_name) ;
430437 copy_dir ( & src_path, & dest_path) ?;
431438 paths. push ( dest_path) ;
432439 continue ;
433440 } else if framework. ends_with ( ".dylib" ) {
434441 let src_path = PathBuf :: from ( & framework) ;
435442 if !src_path. exists ( ) {
436- return Err ( crate :: Error :: FrameworkNotFound ( framework. to_string ( ) ) ) ;
443+ return Err ( Error :: FrameworkNotFound ( framework. to_string ( ) ) ) ;
437444 }
438445 let src_name = src_path
439446 . file_name ( )
440- . ok_or_else ( || crate :: Error :: FailedToExtractFilename ( src_path. clone ( ) ) ) ?;
447+ . ok_or_else ( || Error :: FailedToExtractFilename ( src_path. clone ( ) ) ) ?;
441448 fs:: create_dir_all ( & dest_dir) ?;
442449 let dest_path = dest_dir. join ( src_name) ;
443450 fs:: copy ( & src_path, & dest_path)
444451 . map_err ( |e| Error :: CopyFile ( src_path. clone ( ) , dest_path. clone ( ) , e) ) ?;
445452 paths. push ( dest_path) ;
446453 continue ;
447454 } else if framework. contains ( '/' ) {
448- return Err ( crate :: Error :: InvalidFramework {
455+ return Err ( Error :: InvalidFramework {
449456 framework : framework. to_string ( ) ,
450457 reason : "framework extension should be either .framework, .dylib or .app" ,
451458 } ) ;
@@ -466,7 +473,7 @@ fn copy_frameworks_to_bundle(
466473 continue ;
467474 }
468475
469- return Err ( crate :: Error :: FrameworkNotFound ( framework. to_string ( ) ) ) ;
476+ return Err ( Error :: FrameworkNotFound ( framework. to_string ( ) ) ) ;
470477 }
471478 }
472479
@@ -482,3 +489,55 @@ fn remove_extra_attr(app_bundle_path: &Path) -> crate::Result<()> {
482489 . map ( |_| ( ) )
483490 . map_err ( crate :: Error :: FailedToRemoveExtendedAttributes )
484491}
492+
493+ // Copies the embedded.provisionprofile file to the Contents directory, if needed.
494+ fn copy_embedded_provisionprofile_file (
495+ contents_directory : & Path ,
496+ config : & Config ,
497+ ) -> crate :: Result < ( ) > {
498+ if let Some ( embedded_provisionprofile_file) = config
499+ . macos ( )
500+ . and_then ( |m| m. embedded_provisionprofile_path . as_ref ( ) )
501+ {
502+ if !embedded_provisionprofile_file. exists ( ) {
503+ return Err ( crate :: Error :: EmbeddedProvisionprofileFileNotFound (
504+ embedded_provisionprofile_file. to_path_buf ( ) ,
505+ ) ) ;
506+ }
507+
508+ fs:: copy (
509+ embedded_provisionprofile_file,
510+ contents_directory. join ( "embedded.provisionprofile" ) ,
511+ )
512+ . map_err ( |e| {
513+ crate :: Error :: FailedToCopyEmbeddedProvisionprofile (
514+ embedded_provisionprofile_file. to_path_buf ( ) ,
515+ e,
516+ )
517+ } ) ?;
518+ }
519+ Ok ( ( ) )
520+ }
521+
522+ // Copies app structures that may need to be embedded inside this app.
523+ #[ tracing:: instrument( level = "trace" , skip( config) ) ]
524+ fn copy_embedded_apps ( contents_directory : & Path , config : & Config ) -> crate :: Result < Vec < PathBuf > > {
525+ let mut paths = Vec :: new ( ) ;
526+
527+ if let Some ( embedded_apps) = config. macos ( ) . and_then ( |m| m. embedded_apps . as_ref ( ) ) {
528+ let dest_dir = contents_directory. join ( "MacOS" ) ;
529+
530+ for embedded_app in embedded_apps {
531+ let src_path = PathBuf :: from ( embedded_app) ;
532+ let src_name = src_path
533+ . file_name ( )
534+ . ok_or_else ( || Error :: FailedToExtractFilename ( src_path. clone ( ) ) ) ?;
535+ let dest_path = dest_dir. join ( src_name) ;
536+ copy_dir ( & src_path, & dest_path) ?;
537+
538+ tracing:: debug!( "Copied embedded app: {:?}" , dest_path) ;
539+ paths. push ( dest_path) ;
540+ }
541+ }
542+ Ok ( paths)
543+ }
0 commit comments