;izdZddlZddlZddlZddlZddlZddlZddlmZm Z m Z m Z m Z m Z mZmZmZmZmZmZmZddlmZddlZddlmZddlmZejeZ dZ!dZ"dZ#d Z$d Z%d Z&d Z'd e(de)fdZ*dZ+dZ,dZ-dZ.Gdde/Z0Gdde/Z1dZ2d#dZ3dZ4d#dZ5dZ6d$dZ7dZ8d Z9d!Z:d"Z;dS)%z Utils for macOS platform. N) LC_BUILD_VERSIONLC_CODE_SIGNATURE LC_ID_DYLIB LC_LOAD_DYLIBLC_LOAD_UPWARD_DYLIBLC_LOAD_WEAK_DYLIBLC_PREBOUND_DYLIBLC_REEXPORT_DYLIBLC_RPATH LC_SEGMENT_64 LC_SYMTABLC_UUIDLC_VERSION_MIN_MACOSX)MachO)compatcht}|r!tj|rdSdS)z 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 IC:\PYTHON\MyICR_Workspace\venv\Lib\site-packages\PyInstaller/utils/osx.pyis_homebrew_envr.9%&&Jf(33J??t 5cht}|r!tj|rdSdS)z Check if Python interpreter was installed via Macports command 'port'. :return: True if Macports else otherwise. TF)get_macports_prefixrrrrs ris_macports_envr;rrctjd}tjtj|}|S)z9 :return: Root path of the Homebrew environment. brewshutilwhichospathdirnameprefixs rrrH9\& ! !F W__RW__V44 5 5F Mrctjd}tjtj|}|S)z9 :return: Root path of the Macports environment. portr!r's rrrRr)rcd|jD}t|dksJdt|d|dS)zJ Helper that finds the version command in the given MachO header. cHg|]}|djtthv| Sr)cmdrr.0r/s r z%_find_version_cmd..bs/mmm3SVZDTVkCl5l5l35l5l5lrzNExpected exactly one LC_BUILD_VERSION or LC_VERSION_MIN_MACOSX command, found !r)commandslen)header version_cmds r_find_version_cmdr9\s] nm&/mmmK {  q lY\]hYiYilll ! q>rct|}|jd}t|}t|djS)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 rr3)rheadersr9 _hex_tripletsdk)filenamebinaryr7r8s rget_macos_sdk_versionr@hs=8__F ^A F#F++K  A* + ++rc6|dzdz }|dzdz }|dz}|||fS)Nii)versionmajorminorrevisions rr<r<ws6 x B &E v ! #E$H % !!rr>returncDg}t|jD]h}t|}|djtkr!||djH||djittt|S)z} Get the -macosx-version-min used to compile a macOS binary. For fat binaries, the minimum version is selected. rr3) rr;r9r/rappendrFminosminmapr<)r>versionsr7r/s rmacosx_version_minrQs H//)**'' q6:. . . OOCFN + + + + OOCFL ) ) ) ) s<** + ++rcd|cxkrdks nJdd|cxkrdks nJdd|cxkrdks nJdt|}|jd}t|}|dz|dzz|z|d_t |jd 5}||d d d d S#1swxYwYd S) 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. rrDzInvalid major version value!zInvalid minor version value!zInvalid revision value!rBrCr3rb+N)rr;r9r=openr>write)r>rGrHrIr?r7r8fps rset_macos_sdk_versionrWsU          <             <        C     !:    8__F ^A F#F++K"uz1Hg|]}|djtk|Sr.)r/rr0s rr2z,fix_exe_for_code_signing..s)RRR#a&*@Q2Q2Q2Q2Q2Qrrz#Executable contains code signature!s__LINKEDITcbg|]+}|djtk|djk)|,S)rr3)r/r segname)r1r/__LINKEDIT_NAMEs rr2z,fix_exe_for_code_signing..s>xxxCc!fjM6Q6QVYZ[V\VdhwVwVwCVwVwVwrr3z(Expected exactly one __LINKEDIT segment!c>g|]}|djtk|Sr.)r/r r0s rr2z,fix_exe_for_code_signing..s(LLL#CFJ)4K4K#4K4K4Krz$Expected exactly one SYMTAB section!arm64i@irSN) FAT_MAGIC FAT_MAGIC_64fat_arch fat_arch64 fat_headerc:g|]}SrE from_fileobj)r1irbrVs rr2z,fix_exe_for_code_signing..s'QQQq..r22QQQrc:g|]}SrErf)r1rhrcrVs rr2z,fix_exe_for_code_signing..s'SSS0044SSSr)"r$r%getsizerr;r5r6offsetstroffstrsizefileofffilesize_get_arch_stringr7rmathceilvmsizerTrUfatmacholib.mach_or`rarbrcrdrgmagicrange nfat_archsizeseek to_fileobj)r> file_size executabler7sign_sec linkedit_seg symtab_sec page_sizer`rardrtarchsarchr]rbrcrVs @@@@rfix_exe_for_code_signingrs())IxJ   #FSRvRRRH x==A   D   R>RSSS9D!DK/DI GGAJJJ NN2    $ $#### $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $$$s%7FF F C J""J&)J&c|j}|jdz}|dkr |dkrdSdS|dkr |dkrdSd S|d krd SJd )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. iirCx86_64hx86_64i arm64er_i386FzUnhandled architecture!)cputype cpusubtype)r7rrs rrprpsp nG"Z/J.  ??98 O # # ??87 Av++++5rc ddl}|}t|d5 t fddD]}|| dddn #1swxYwYt |}|jD]}d|jD}|s|d}|dj}| } | || dd} t| dksJ| |d_t|d 5 | ddddS#1swxYwYdS) aG 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 rNrbc.dS)Ni )read)rVsrz'update_exe_identifier..&s"''$--rrc>g|]}|djtk|Sr.)r/rr0s rr2z)update_exe_identifier..-s(LLLCc!fjG6K6KC6K6K6Krr3rBrS) hashlibsha1rTiterupdaterr;r5uuidcopydigestr6rU) r> pkg_filenamerpkg_hashchunkr}r7uuid_cmd original_uuid combined_hashnew_uuidrVs @rupdate_exe_identifierrsNNN||~~H lD ! !#R////55 # #E OOE " " " " ################ xJ$$$LL6?LLL  A;! ( !  ]+++ ''))#2#.8}}""""#  h  "s#,A##A'*A''E  EEceZdZdZdS)InvalidBinaryErrorz] Exception raised by `get_binary_architectures` when it is passed an invalid binary. N)__name__ __module__ __qualname____doc__rErrrrEs Drrc"eZdZdZfdZxZS)IncompatibleBinaryArchErrorzq Exception raised by `binary_to_target_arch` when the passed binary fails the strict architecture check. cXd}t|d|dS)NzMhttps://pyinstaller.org/en/stable/feature-notes.html#macos-multi-arch-supportz, For details about this error message, see: )super__init__)selfmessageurl __class__s rrz$IncompatibleBinaryArchError.__init__Ps5] GVVQTVVWWWWWr)rrrrr __classcell__)rs@rrrLsKXXXXXXXXXrrc t|}n"#t$r}td|d}~wwxYwt|jd|jDfS)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. zInvalid Mach-O binary!Nc6g|]}t|jSrE)rpr7)r1hdrs rr2z,get_binary_architectures..^s#!]!]!]3"23:">">!]!]!]r)r ValueErrorrboolrtr;)r>r}es rget_binary_architecturesrUsp B8__ BBB !9::AB    !]!]*J\!]!]!] ]]s 1,1c|p|}dd||d|g}tj|tjtjd}|jr"t d|d|jd|jd S) z\ Convert the given fat binary into thin one with the specified target architecture. lipoz-thin-outpututf-8stdoutstderrencodinglipo command () failed with error code ! output: N subprocessrunPIPESTDOUT returncode SystemErrorr)r> thin_archoutput_filenamecmd_argsps rconvert_binary_to_thin_archras&1OHiQHx  @Q\cdddA|sq8qqalqqghgoqqrrrssrcddd|g|}tj|tjtjd}|jr"t d|d|jd|jd S) zJ Merge the given single-arch thin binary files into a fat binary. rz-createrrrrrrNr)rslice_filenamesrrs rmerge_into_fat_binaryrlsy 9oPPHx  @Q\cdddA|sq8qqalqqghgoqqrrrssrcB|s|}t|\}}|dkr|st|dd S|rH||vrt|d|dtd|||t ||d S||vrt|d|d|dd d S) 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 r4z1Converting fat binary %s (%s) to thin binary (%s)z" is incompatible with target arch z (has arch: rz)!N)rrloggerdebugr)r> target_arch display_nameis_fatrs rbinary_to_target_archrvs   ,X66MFEl"" V-.T.T.TUU U V V  %''1\2m2m_j2m2m2mnnn LLLhXdfq r r r '+ > > > > >%''1#ll{ll`efg`hlll('rctd|ddd|g}tj|tjtjd}|jr"td|d|jd |jd S) zp Remove the signature from all architecture slices of the given binary file using the codesign utility. zRemoving signature from file %r/usr/bin/codesignz--remove--all-architecturesrrcodesign command (rrN) rrrrrrrrr)r>rrs rremove_signature_from_binaryrs LL2H===#Z1FQHx  @Q\cdddA|wuxuuRSR^uuklksuuvvvwwrFcg}|sd}n|d|r*|d|||r|dtd|dd|dd d g||}tj|tjtjd }|jr"td |d|jd|j dS)zj Sign the binary using codesign utility. If no identity is provided, ad-hoc signing is performed. -z--options=runtimez--entitlementsz--deepzSigning file %rrz-sz--forcerz --timestamprrrrrN) rLrrrrrrrrr)r>identityentitlements_filedeep extra_argsrrs r sign_binaryrsJ /-...-*++++,,, $(### LL"H---T8Y8M}_iksH x  @Q\cdddA|wuxuuRSR^uuklksuuvvvwwrct|\}}|rtj5}g}|D]Y}tj||}t |||t||||Zt|g|RddddS#1swxYwYdSt||dS)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/` 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. )rN) rtempfileTemporaryDirectoryr$r%joinr_set_dylib_dependency_pathsrLr)r> target_rpathrrtmpdirrrslice_filenames rset_dylib_dependency_pathsrs $-X66MFE <  ( * * >f O 7 7!#fd!;!;+HdN[[[[+NLIII&&~6666 !( =_ = = = = > > > > > > > > > > > > > > > > > > $Hl;;;;;sA,B!!B%(B%cttttth}t |}d}t }t }|jD]}|jD]}|dj } | |vr| tthvr$|d d d} | |vr|| l| tkr|| | tkr| }~d} |r;tt!jdt!j|jz } g} d} |D]t&jr"dd g}t-fd |DrBd } tt!jdt!jjz }|kr| |fg}| r | |kr|d | gz }| D] \}}|d ||gz }|D]}||kr |d|gz }| r ||vr|d|gz }|sdSdg||}t1j|t0jt0jd}|jr"t;d|d|jd|jdS)z The actual implementation of set_dylib_dependency_paths functionality. Implicitly assumes that a single-arch thin binary is given. Nrrrz@rpathFz"/Library/Frameworks/Tcl.framework/z!/Library/Frameworks/Tk.framework/cg|]}|vSrErE)r1x linked_libs rr2z/_set_dylib_dependency_paths..s555AZ555rTz-idz-changez -delete_rpathz -add_rpathinstall_name_toolrzinstall_name_tool command (rr)rrrr r rsetr;r5r/r rdecoderstripaddstrpathlibPurePathnamemacholibutilin_system_pathanyrLrrrrrrr)r>r _RELOCATABLEr?dylib_idrpaths linked_libsr7r/lc_typer%normalized_dylib_idchanged_lib_pathsrpath_required _exemptionsnew_pathinstall_name_tool_args original_pathrpathrrrs @rrrsY  L8__FH UUF%%K.  ? C!fjGl**wx>U/U/Uq6==))0088D,&&%%%%H$$ 4    K''  `!'"28"<">5*=">>$5GG x9mX"FF   L   #   ,f44  #   "$G&<GhGHx  @Q\cdddA|  p( p pQ\ p pfgfn p p     rctj|}|jjjdkrdS|jjjj|jdzkrdSdS)zK Check if the given shared library is part of a .framework bundle. VersionsFz .frameworkT)rrparentr)lib_paths ris_framework_bundle_librQsU ))H"j00u$)X]\-IIIu 4rc Dd}t}t}|D]\}}}|dkrtj|}tj|}t |sFt |sV|jdz dz } | s{|jjjdz dz } | sNd}|jjj} tjrtd| dt d| | } |jdz dz } | t| t| d f| t|jjd z t|jjd f|jjj} | t| |jz ttjd |jz d f| t| dz d d f| | ddh}|D]} |D]\}}}tj|} || }n#t $rY=wxYw|j}|ddkrU|d}||vrb| t| |z ttjd |z d f|rt dt%|S)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/` directory containing the binary - `` in the top-level .framework directory, pointing to `Versions/Current/` - `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. FBINARY Resourcesz Info.plistTzCould not find Info.plist in r4z Could not find Info.plist in %s!DATACurrentSYMLINKzVersions/CurrentzVersions/Current/ResourcesHelpersrrrzOne 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.)rrPathrrris_filerstrict_collect_moderrwarningrrr relative_torpartssorted)collected_filesinvalid_framework_foundframework_filesframework_paths dest_namesrc_nametypecodesrc_path dest_pathinfo_plist_srcinfo_plist_src_top framework_dirinfo_plist_destdest_framework_path VALID_SUBDIRSremaining_pathremaining_path_partsdir_names r$collect_files_from_framework_bundlesr5as$eeOeeO*9=1=1% 8X x   <))$Y// 'x00  'y11  ";6E%%'' 0"*!7!>!L|![ %--//  +/' ( 6 = -%&Vm&V&V&VWWWNN#E}UUU/N#*[8<GS113~3F3FOPPP S!1!89!DEEs9K[K`GaGaclmnnn'.5<  #in4 5 5  !344y~E F F       #k1 2 2 (      /0000  ,M.-<   )Ix(33I !*!6!67J!K!K    $2#7 $A&*44,A.H},,   '(233G$%7888CDD!    ) 8  H   / " ""s$I:: JJ)N)NNF)r?s(  ! !!!!!!  8 $ $          , , ,""",,,,,,$,Z$Z$Z$z,,,.'''T        XXXXX)XXX ^ ^ ^sssssss8wwwwwww0<<