
    iz                        S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJrJ	r	J
r
JrJrJrJrJrJrJrJrJrJr  SSKJr  SSKrSSKJr  SSKJr  \R<                  " \5      r S r!S r"S r#S	 r$S
 r%S r&S r'S\(S\)4S jr*S r+S r,S r-S r. " S S\/5      r0 " S S\/5      r1S r2S"S jr3S r4S"S jr5S r6S#S jr7S r8S r9S  r:S! r;g)$z
Utils for macOS platform.
    N)LC_BUILD_VERSIONLC_CODE_SIGNATURELC_ID_DYLIBLC_LOAD_DYLIBLC_LOAD_UPWARD_DYLIBLC_LOAD_WEAK_DYLIBLC_PREBOUND_DYLIBLC_REEXPORT_DYLIBLC_RPATHLC_SEGMENT_64	LC_SYMTABLC_UUIDLC_VERSION_MIN_MACOSX)MachO)compatc                  p    [        5       n U (       a%  [        R                  R                  U 5      (       a  gg)zs
Check if Python interpreter was installed via Homebrew command 'brew'.

:return: True if Homebrew else otherwise.
TF)get_homebrew_prefixr   base_prefix
startswith
env_prefixs    BC:\des-py\RoboSAPF\venv\Lib\site-packages\PyInstaller/utils/osx.pyis_homebrew_envr   .   +     %&Jf((33J??    c                  p    [        5       n U (       a%  [        R                  R                  U 5      (       a  gg)zs
Check if Python interpreter was installed via Macports command 'port'.

:return: True if Macports else otherwise.
TF)get_macports_prefixr   r   r   r   s    r   is_macports_envr   ;   r   r   c                      [         R                  " S5      n [        R                  R	                  [        R                  R	                  U 5      5      n U $ )z1
:return: Root path of the Homebrew environment.
brewshutilwhichospathdirnameprefixs    r   r   r   H   6     \\&!FWW__RWW__V45FMr   c                      [         R                  " S5      n [        R                  R	                  [        R                  R	                  U 5      5      n U $ )z1
:return: Root path of the Macports environment.
portr!   r'   s    r   r   r   R   r)   r   c                     U R                    Vs/ s H#  oS   R                  [        [        1;   d  M!  UPM%     nn[	        U5      S:X  d   S[	        U5       S35       eUS   $ s  snf )zB
Helper that finds the version command in the given MachO header.
r      zNExpected exactly one LC_BUILD_VERSION or LC_VERSION_MIN_MACOSX command, found !)commandscmdr   r   len)headerr0   version_cmds      r   _find_version_cmdr4   \   sq     #)//m/3VZZDTVkCl5l3/Km{q  m
XY\]hYiXjjklm q> ns
    A#A#c                 |    [        U 5      nUR                  S   n[        U5      n[        US   R                  5      $ )z
Obtain the version of macOS SDK against which the given binary was built.

NOTE: currently, version is retrieved only from the first arch slice in the binary.

:return: (major, minor, revision) tuple
r   r-   )r   headersr4   _hex_tripletsdk)filenamebinaryr2   r3   s       r   get_macos_sdk_versionr;   h   s:     8_F^^AF#F+KA**++r   c                 4    U S-  S-	  nU S-  S-	  nU S-  nXU4$ )Ni      i          )versionmajorminorrevisions       r   r7   r7   w   s4    xB&Ev!#E$H!!r   r9   returnc                 0   / n[        U 5      R                   Hc  n[        U5      nUS   R                  [        :X  a   UR                  US   R                  5        ME  UR                  US   R                  5        Me     [        [        [        U5      5      $ )zq
Get the -macosx-version-min used to compile a macOS binary.

For fat binaries, the minimum version is selected.
r   r-   )r   r6   r4   r0   r   appendrA   minosminmapr7   )r9   versionsr2   r0   s       r   macosx_version_minrL      sv     H/))'q6::..OOCFNN+ OOCFLL) * s<*++r   c                    SUs=::  a  S::  d   S5       e   S5       eSUs=::  a  S::  d   S5       e   S5       eSUs=::  a  S::  d   S5       e   S5       e[        U 5      nUR                  S   n[        U5      nUS-  US-  -  U-  US   l        [	        UR
                  S	5       nUR                  U5        S
S
S
5        g
! , (       d  f       g
= f)z
Overwrite the macOS SDK version declared in the given binary with the specified version.

NOTE: currently, only version in the first arch slice is modified.
r   r?   zInvalid major version value!zInvalid minor version value!zInvalid revision value!r=   r>   r-   rb+N)r   r6   r4   r8   openr9   write)r9   rB   rC   rD   r:   r2   r3   fps           r   set_macos_sdk_versionrR      s     <<<<<<<<<<<<C:!:::!::8_F^^AF#F+K"uz1H<KN	foou	%R 
&	%	%s   &C
Cc                    [         R                  R                  U 5      n[        U 5      nUR                  S   nUR
                   Vs/ s H  oDS   R                  [        :X  d  M  UPM     nn[        U5      S:X  d   S5       eSnUR
                   Vs/ s H2  oDS   R                  [        :X  d  M  US   R                  U:X  d  M0  UPM4     nn[        U5      S:X  d   S5       eUS   S   nUR
                   Vs/ s H  oDS   R                  [        :X  d  M  UPM     nn[        U5      S:X  d   S5       eUS   S   nXR                  UR                  -   -
  Ul        XR                  UR                  -   -
  Ul        [#        UR$                  5      R'                  S5      (       a  S	OS
n	[(        R*                  " UR                   U	-  5      U	-  Ul        [/        U S5       n
UR1                  U
5        SSS5        UR2                  (       Ga  SSKJnJnJnJnJn  [/        U S5       n
URA                  U
5      nURB                  U:X  a5  [E        URF                  5       Vs/ s H  nURA                  U
5      PM     nnODURB                  U:X  a4  [E        URF                  5       Vs/ s H  nURA                  U
5      PM     nnWS   nUUR                  -
  Ul$        U
RK                  S5        URM                  U
5        U H  nURM                  U
5        M     SSS5        ggs  snf s  snf s  snf ! , (       d  f       GND= fs  snf s  snf ! , (       d  f       g= f)a  
Fixes the Mach-O headers to make code signing possible.

Code signing on macOS does not work out of the box with embedding .pkg archive into the executable.

The fix is done this way:
- Make the embedded .pkg archive part of the Mach-O 'String Table'. 'String Table' is at end of the macOS exe file,
  so just change the size of the table to cover the end of the file.
- Fix the size of the __LINKEDIT segment.

Note: the above fix works only if the single-arch thin executable or the last arch slice in a multi-arch fat
executable is not signed, because LC_CODE_SIGNATURE comes after LC_SYMTAB, and because modification of headers
invalidates the code signature. On modern arm64 macOS, code signature is mandatory, and therefore compilers
create a dummy signature when executable is built. In such cases, that signature needs to be removed before this
function is called.

Mach-O format specification: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/Mach-O.5.html
r   z#Executable contains code signature!s   __LINKEDIT      r-   z(Expected exactly one __LINKEDIT segment!z$Expected exactly one SYMTAB section!arm64i @  i   rN   N)	FAT_MAGICFAT_MAGIC_64fat_arch
fat_arch64
fat_header)'r$   r%   getsizer   r6   r/   r0   r   r1   r   segnamer   offsetstroffstrsizefileofffilesize_get_arch_stringr2   r   mathceilvmsizerO   rP   fatmacholib.mach_orV   rW   rX   rY   rZ   from_fileobjmagicrange	nfat_archsizeseek
to_fileobj)r9   	file_size
executabler2   r0   sign_sec__LINKEDIT_NAMElinkedit_seg
symtab_sec	page_sizerQ   rV   rW   rX   rY   rZ   rf   iarchsarchs                       r   fix_exe_for_code_signingry      s   ( )I xJ#F  &Ra&**@Q2QHRx=ADDD <O#)??x?C!fjjM6QCVYZ[V\VdVdhwVwC?Lx|!M#MM!?1%L!'L#FJJ)4K#JLz?aG!GGAq!J  #mmj6G6G&GHJ%9M9M)MNL ,FMM:EEgNNTZI))L$9$9I$EFRL 
h	" 

 ~~~__(E"b ))"-CyyI%<A#--<PQ<Pq..r2<PQl*>CCMM>RS>R004>RS9D!DKK/DIGGAJNN2#  #" Y S
 y M< 
	 RS #"sa   L#&L#L(2L(L(;L-L-#L2)9M"M=*M'M	AM2
M
M
Mc                     U R                   nU R                  S-  nUS:X  a  US:X  a  ggUS:X  a  US:X  a  gg	US
:X  a  g S5       e)z
Converts cputype and cpusubtype from mach_o.mach_header_64 into arch string comparible with lipo/codesign.
The list of supported architectures can be found in man(1) arch.
ii  r>   x86_64hx86_64i     arm64erU      i386zUnhandled architecture!)cputype
cpusubtype)r2   r   r   s      r   rb   rb     s\     nnG""Z/J. ?	O	#?	A+++5r   c                   ^ SSK nUR                  5       n[        US5       m[        U4S jS5       H  nUR	                  U5        M     SSS5        [        U 5      nUR                   H  nUR                   Vs/ s H  owS   R                  [        :X  d  M  UPM     nnU(       d  M@  US   nUS   R                  n	UR                  5       n
U
R	                  U	5        U
R                  5       SS n[        U5      S:X  d   eXS   l
        M     [        U S5       mUR                  T5        SSS5        g! , (       d  f       N= fs  snf ! , (       d  f       g= f)	a7  
Modifies the Mach-O image UUID stored in the LC_UUID command (if present) in order to ensure that different
frozen applications have different identifiers. See TN3178 for details on why this is required:
https://developer.apple.com/documentation/technotes/tn3178-checking-for-and-resolving-build-uuid-problems
r   Nrbc                  &   > T R                  S5      $ )Ni    )read)rQ   s   r   <lambda>'update_exe_identifier.<locals>.<lambda>&  s    "''$-r   r   r-   r=   rN   )hashlibsha1rO   iterupdater   r6   r/   r0   r   uuidcopydigestr1   rP   )r9   pkg_filenamer   pkg_hashchunkrp   r2   r0   uuid_cmdoriginal_uuidcombined_hashnew_uuidrQ   s               @r   update_exe_identifierr     s)    ||~H	lD	!R/5EOOE" 6 
"
 xJ$$#)??L?C!fjjG6KC?LA; !((
 !]+ '')#2.8}"""#' %, 
h	" 
	9 
"	! M( 
	s#   )D7;EEE7
E
Ec                       \ rS rSrSrSrg)InvalidBinaryErroriE  zU
Exception raised by `get_binary_architectures` when it is passed an invalid binary.
r@   N)__name__
__module____qualname____firstlineno____doc____static_attributes__r@   r   r   r   r   E  s     	r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )IncompatibleBinaryArchErroriL  zi
Exception raised by `binary_to_target_arch` when the passed binary fails the strict architecture check.
c                 2   > Sn[         TU ]  U SU 35        g )NzMhttps://pyinstaller.org/en/stable/feature-notes.html#macos-multi-arch-supportz, For details about this error message, see: )super__init__)selfmessageurl	__class__s      r   r   $IncompatibleBinaryArchError.__init__P  s#    ]G9$PQTPUVWr   r@   )r   r   r   r   r   r   r   __classcell__)r   s   @r   r   r   L  s    X Xr   r   c                      [        U 5      n[        UR                  5      UR
                   Vs/ s H  n[        UR                  5      PM     sn4$ ! [         a  n[        S5      UeSnAff = fs  snf )z
Inspects the given binary and returns tuple (is_fat, archs), where is_fat is boolean indicating fat/thin binary,
and arch is list of architectures with lipo/codesign compatible names.
zInvalid Mach-O binary!N)r   
ValueErrorr   boolrf   r6   rb   r2   )r9   rp   ehdrs       r   get_binary_architecturesr   U  sl    
B8_
 
*J\J\!]J\3"23::">J\!]]]  B !9:AB!]s   A A0
A-A((A-c                     U=(       d    U nSSXSU/n[         R                  " U[         R                  [         R                  SS9nUR                  (       a(  [        SU SUR                   SUR                   35      eg	)
zT
Convert the given fat binary into thin one with the specified target architecture.
lipoz-thin-outpututf-8stdoutstderrencodinglipo command () failed with error code 
!
output: N
subprocessrunPIPESTDOUT
returncodeSystemErrorr   )r9   	thin_archoutput_filenamecmd_argsps        r   convert_binary_to_thin_archr   a  su     &1OiQHx

@Q@Q\cdA||N8*4Mall^[fghgogofpqrr r   c                     SSSU /UQn[         R                  " U[         R                  [         R                  SS9nUR                  (       a(  [        SU SUR                   SUR                   35      eg	)
zB
Merge the given single-arch thin binary files into a fat binary.
r   z-creater   r   r   r   r   r   Nr   )r   slice_filenamesr   r   s       r   merge_into_fat_binaryr   l  sn     	9oPPHx

@Q@Q\cdA||N8*4Mall^[fghgogofpqrr r   c                     U(       d  U n[        U 5      u  p4US:X  a  U(       d  [        U S35      eg
U(       a9  X;  a  [        U SU S35      e[        R                  SXU5        [	        X5        g
X;  a  [        U SU SUS    S	35      eg
)z}
Check that the given binary contains required architecture slice(s) and convert the fat binary into thin one,
if necessary.

universal2z is not a fat binary!z does not contain slice for r.   z1Converting fat binary %s (%s) to thin binary (%s)z" is incompatible with target arch z (has arch: r   z)!N)r   r   loggerdebugr   )r9   target_archdisplay_nameis_fatrw   s        r   binary_to_target_archr   v  s    
 ,X6MFl"->S.TUU  '1\NB^_j^kkl2mnnLLLhfqr'>'1#n$F{mS_`efg`h_iikl  (r   c                    [         R                  SU 5        SSSU /n[        R                  " U[        R                  [        R
                  SS9nUR                  (       a(  [        SU SUR                   S	UR                   35      eg
)zh
Remove the signature from all architecture slices of the given binary file using the codesign utility.
zRemoving signature from file %r/usr/bin/codesignz--remove--all-architecturesr   r   codesign command (r   r   N)	r   r   r   r   r   r   r   r   r   )r9   r   r   s      r   remove_signature_from_binaryr     s~     LL2H=#Z1FQHx

@Q@Q\cdA||.xj8QRSR^R^Q__jklksksjtuvv r   c                    / nU(       d  SnOUR                  S5        U(       a"  UR                  S5        UR                  U5        U(       a  UR                  S5        [        R                  SU 5        SSUSS	S
/UQU Pn[        R                  " U[        R
                  [        R                  SS9nUR                  (       a(  [        SU SUR                   SUR                   35      eg)zb
Sign the binary using codesign utility. If no identity is provided, ad-hoc signing is performed.
-z--options=runtimez--entitlementsz--deepzSigning file %rr   z-sz--forcer   z--timestampr   r   r   r   r   N)
rG   r   r   r   r   r   r   r   r   r   )r9   identityentitlements_filedeep
extra_argsr   r   s          r   sign_binaryr     s     J-.*++,(#
LL"H-T8Y8M}_iksH 	x

@Q@Q\cdA||.xj8QRSR^R^Q__jklksksjtuvv r   c                 Z   [        U 5      u  p#U(       a{  [        R                  " 5        n/ nU HH  n[        R                  R                  XF5      n[        XUS9  [        Xq5        UR                  U5        MJ     [        U /UQ76   SSS5        g[        X5        g! , (       d  f       g= f)a  
Modify the given dylib's identity (in LC_ID_DYLIB command) and the paths to dependent dylibs (in LC_LOAD_DYLIB)
commands into `@rpath/<basename>` format, remove any existing rpaths (LC_RPATH commands), and add a new rpath
(LC_RPATH command) with the specified path.

Uses `install-tool-name` utility to make the changes.

The system libraries (e.g., the ones found in /usr/lib) are exempted from path rewrite.

For multi-arch fat binaries, this function extracts each slice into temporary file, processes it separately,
and then merges all processed slices back into fat binary. This is necessary because `install-tool-name` cannot
modify rpaths in cases when an existing rpath is present only in one slice.
)r   N)
r   tempfileTemporaryDirectoryr$   r%   joinr   _set_dylib_dependency_pathsrG   r   )r9   target_rpathr   rw   tmpdirr   rx   slice_filenames           r   set_dylib_dependency_pathsr     s    $ -X6MF((*f O!#f!;+HN[+NI&&~6	 
 "(=_= +* 	$H; +*s   AB
B*c                    [         [        [        [        [        1n[        U 5      nSn[        5       n[        5       nUR                   H  nUR                   H  nUS   R                  n	X;  a  U	[        [        1;  a  M)  US   R                  S5      R                  S5      n
X;   a  UR                  U
5        Md  U	[        :X  a  UR                  U
5        M  U	[        :X  d  M  U
nM     M     ASnU(       a@  [        [         R"                  " S5      [         R"                  " U5      R$                  -  5      n/ nSnU H  n[&        R(                  R+                  U5      (       a  M)  SS	/n[-        U Vs/ s H  nUU;   PM
     sn5      (       a  MS  S
n[        [         R"                  " S5      [         R"                  " U5      R$                  -  5      nUU:X  a  M  UR/                  UU45        M     / nU(       a  X:w  a  USU/-  nU H  u  nnUSUU/-  nM     U H  nUU:X  a  M  USU/-  nM     U(       a  X;  a  USU/-  nU(       d  gS/UQU Pn[0        R2                  " U[0        R4                  [0        R6                  SS9nUR8                  (       a(  [;        SU SUR8                   SUR<                   35      egs  snf )z
The actual implementation of set_dylib_dependency_paths functionality.

Implicitly assumes that a single-arch thin binary is given.
Nr   r}   r    z@rpathFz"/Library/Frameworks/Tcl.framework/z!/Library/Frameworks/Tk.framework/Tz-idz-changez-delete_rpathz
-add_rpathinstall_name_toolr   zinstall_name_tool command (r   r   )r   r   r   r	   r
   r   setr6   r/   r0   r   r   decoderstripaddstrpathlibPurePathnamemacholibutilin_system_pathanyrG   r   r   r   r   r   r   r   )r9   r   _RELOCATABLEr:   dylib_idrpathslinked_libsr2   r0   lc_typer%   normalized_dylib_idchanged_lib_pathsrpath_required
linked_lib_exemptionsxnew_pathinstall_name_tool_argsoriginal_pathrpathr   r   s                          r   r   r     s    	L 8_FHUF%K..??C!fjjG*wx>U/U q6==)008D&%H$

4 K' # !  	 !'"2"28"<w?O?OPX?Y?^?^"^_
 N!
==''
33 1/
 5AZ566 w''1G4D4DZ4P4U4UUV!  *h!781 "6   2>5*=">> $5x9mX"FF $5
 L #
 	
  ,4#
 	
 " $G&<GhGHx

@Q@Q\cdA||)(3LQ\\NZefgfnfneop
 	
 a 6s   5K
c                     [         R                  " U 5      n U R                  R                  R                  S:w  a  gU R                  R                  R                  R                  U R                  S-   :w  a  gg)zC
Check if the given shared library is part of a .framework bundle.
VersionsFz
.frameworkT)r   r   parentr   )lib_paths    r   is_framework_bundle_libr
  Q  s^    
 )H ""j0$$))X]]\-IIr   c           
         Sn[        5       n[        5       nU  GHO  u  pEnUS:w  a  M  [        R                  " U5      n[        R                  " U5      n[	        U5      (       d  MM  [	        U5      (       d  M_  UR
                  S-  S-  n	U	R                  5       (       d  UR
                  R
                  R
                  S-  S-  n
U
R                  5       (       d_  SnUR
                  R
                  R
                  n[        R                  (       a  [        SU S35      e[        R                  SU5        GM   U
n	UR
                  S-  S-  nUR                  [        U5      [        U	5      S	45        UR                  [        UR
                  R
                  S
-  5      [        UR
                  R                  5      S45        UR
                  R
                  R
                  nUR                  [        XR                  -  5      [        [        R                  " S5      UR                  -  5      S45        UR                  [        US-  5      SS45        UR                  U5        GMR     SS1nU H  nU  H  u  pEn[        R                  " U5      n UR                  U5      nUR"                  nUS   S:w  a  ME  US   nUU;  a  MR  UR                  [        UU-  5      [        [        R                  " S5      U-  5      S45        M     M     U(       a  [        R                  S5        [%        U5      $ ! [          a     M  f = f)a  
Scan the given TOC list of collected files for shared libraries that are collected from macOS .framework bundles,
and collect the bundles' Info.plist files. Additionally, the following symbolic links:
  - `Versions/Current` pointing to the `Versions/<version>` directory containing the binary
  - `<name>` in the top-level .framework directory, pointing to `Versions/Current/<name>`
  - `Resources` in the top-level .framework directory, pointing to `Versions/Current/Resources`
  - additional directories in top-level .framework directory, pointing to their counterparts in `Versions/Current`
    directory.

Returns TOC list for the discovered Info.plist files and generated symbolic links. The list does not contain
duplicated entries.
FBINARY	Resourcesz
Info.plistTzCould not find Info.plist in r.   z Could not find Info.plist in %s!DATACurrentSYMLINKzVersions/CurrentzVersions/Current/ResourcesHelpersr   r  r}   zOne or more collected .framework bundles have missing Info.plist file. If you are building an .app bundle, you will most likely not be able to code-sign it.)r   r   Pathr   r
  r  is_filer   strict_collect_moder   r   warningr   r   r   relative_tor   partssorted)collected_filesinvalid_framework_foundframework_filesframework_paths	dest_namesrc_nametypecodesrc_path	dest_pathinfo_plist_srcinfo_plist_src_topframework_dirinfo_plist_destdest_framework_pathVALID_SUBDIRSremaining_pathremaining_path_partsdir_names                     r   $collect_files_from_framework_bundlesr+  a  s    $eOeO *9%	Xx<<)$$Y/	 'x00 'y11 ";6E%%'' "*!7!7!>!>!L|![%--// +/' ( 6 6 = =--%(Em_TU&VWWNN#E}U/N#**[8<GS13~3FOP
 	S!1!1!8!89!DEs9K[K[K`K`Gaclmn'..55<< 	#nn45  !34y~~EF
 	 	#k12(
 	 	/0{ *9D ,M.-<)I((3I!*!6!67J!K $2#7#7  $A&*4 ,A.H},'(23G$$%788CD! ) .=  /: H	

 /""9  s   L99
MM)N)NNF)<r   rc   r$   r   r   r"   r   rg   r   r   r   r   r   r   r	   r
   r   r   r   r   r   macholib.MachOr   macholib.utilr   PyInstaller.loglogloggingPyInstallerr   	getLoggerr   r   r   r   r   r   r4   r;   r7   r   tuplerL   rR   ry   rb   r   	Exceptionr   r   r   r   r   r   r   r   r   r   r
  r+  r@   r   r   <module>r5     s     	        !  ! 			8	$

	,", , ,$,Z$z,.'T	 	X) X	^ss8ww0<Dw
t ~#r   