o
    (ch                     @  s  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
mZ d dlmZmZmZmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZmZ d dlZd dlm Z! d d	l"m#Z$ d d
l"m%Z% d dl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2m3Z3m4Z4 G dd de+Z5dCddZ6G dd deZ7dDdd Z8dEd"d#Z9dFd)d*Z:dGd0d1Z;e'd2 Z<dHd4d5Z=dId8d9Z>dJd=d>Z?dKdAdBZ@dS )L    )annotationsN)log)CompileErrorDistutilsExecErrorDistutilsFileErrorDistutilsPlatformError)get_config_var)Path)DictIterableList
NamedTupleOptionalSetTuplecast)build)	build_ext)get_abi3_suffix)Literal   )format_called_process_error)RustCommand)BindingRustBinRustExtensionStrip)get_rust_hostget_rust_target_listget_rustc_cfgsc                      s   e Zd ZU dZdZg dZg dZdZded< d- fd
dZ	d- fddZ
d.ddZd/ddZ	d0d1ddZd2ddZd3ddZd4d d!Z	d0d5d"d#Zd6d%d&Zd7d+d,Z  ZS )8
build_rustz+Command for building Rust crates via cargo.z7build Rust extensions (compile/link to build directory)))inplaceiziignore build-lib and put compiled extensions into the source directory alongside your pure Python modules)debugdz,Force debug to true for all Rust extensions )releaserz-Force debug to false for all Rust extensions )qbuildNz2Force enable quiet option for all Rust extensions )z
build-temptz9directory for temporary files (cargo 'target' directory) )ztarget=NzBuild for the target triple)r!   r#   r%   r'   NOptional[str]	plat_namereturnNonec                   sR   t    d | _d | _d | _d | _d | _d | _d | _t	
d| _t	
dd| _d S )NZCARGO_BUILD_TARGETCARGOcargo)superinitialize_optionsr!   r#   r%   r'   
build_tempr*   build_numberosgetenvtargetr.   self	__class__ 9usr/lib/python3.10/site-packages/setuptools_rust/build.pyr0   <   s   
zbuild_rust.initialize_optionsc                   s~   t    |  | _| jd u r!tt| dj| _t| jt	s!J | 
dddd | jd ur;| jd d  s=tdd S d S )Nr   r   )r1   r1   )r#   r#   )r!   r!   r   z1Build tag (build-number) must start with a digit.)r/   finalize_optionsget_data_dirdata_dirr*   r   CommandBuildget_finalized_command
isinstancestrset_undefined_optionsr2   isdigit
ValueErrorr6   r8   r:   r;   r<   H   s$   



zbuild_rust.finalize_optionsrB   c                 C  sP   t | j ddt | j ddf}| jr!|| jf7 }d|d S )N-_z.data)	pkg_resources	safe_namedistributionget_namereplacesafe_versionget_versionr2   join)r7   
componentsr:   r:   r;   r=   ^   s   zbuild_rust.get_data_dirextr   c                 C  s   | j d usJ td}d}| j dr2|r2d|v od|v }|s2| js2d|v r+d| _nd|v r2d| _|rf| |d}| |d}g }t||D ]\\}}\}	}
|dd	}t|||
g |	t
|| qGn| || j}| || d S )
NZ	ARCHFLAGSFmacosx-x86_64arm64zaarch64-apple-darwinx86_64-apple-darwinzaarch64-apple-darwin/ )r*   r3   r4   
startswithr5   build_extensionziprL   create_universal2_binaryappend_BuiltModuleinstall_extension)r7   rQ   Z
arch_flags
universal2Zarm64_dylib_pathsZx86_64_dylib_pathsdylib_pathstarget_fnameZarm64_dylibrG   Zx86_64_dylibZfat_dylib_pathr:   r:   r;   run_for_extensiong   s.   

zbuild_rust.run_for_extensionforced_target_tripleList['_BuiltModule']c              
     sJ  |  |}t|}t }tj|jstd|j | jp |j}| 	|}| j
||| |d}g }	| rB| jdd|jdg|}
nSddg|j}|dd	kretj| ||j}|d
d| g |ddkrr|	d n|d|dfdkr|d
dg | jdddd|jg|d|}
|	r|d}|d ur|	| d|	}||d< |std| ddtjd |std|
tjd z|rtjnd }tj|
||dd}W n tjy } ztt|ddd }~w ty   tdw g }|j |d d! d" }| rbt!|" |d#hd$}|j#$ D ]E\ } s(|%d%d&  zt& fd'd(|D }W n t'yE   td)  d*w tj(d+d,krVt)|||d }|t*|| q|S t!|" |dd-hd$}t+|d.krxtd/t+|d0krtd1| |d. }tj(d+d,krt)|||d }|t*|j| |S )2Nz(can't find Rust extension project file: )rQ   target_tripler%   quietr   z--manifest-pathz(--message-format=json-render-diagnosticsz--crate-typeZcdylibZ	target_osZmacosz-Cz=link-args=-undefined dynamic_lookup -Wl,-install_name,@rpath/
target_envmuslz-Ctarget-feature=-crt-statictarget_arch)Zwasm32Z
emscriptenz'link-args=-sSIDE_MODULE=2 -sWASM_BIGINTZrustcz--libz--Z	RUSTFLAGS z[RUSTFLAGS=])endfile)rl   T)envstderrtextF)Zinclude_stdoutzbUnable to execute 'cargo' - this package requires Rust to be installed and cargo to be on the PATH)re   resolverootbin)
package_idkinds.c                 3  s(    | ]}t |d j kr|V  qdS )rV   N)r	   with_suffixname).0Zartifactrx   r:   r;   	<genexpr>  s    z-build_rust.build_extension.<locals>.<genexpr>z0Rust build failed; unable to locate executable ''r-   crossdylibr   zERust build failed; unable to find any cdylib or dylib build artifactsr   zNRust build failed; expected only one cdylib or dylib build artifact but found ),_detect_rust_targetr   _prepare_build_environmentr3   pathexistsr   r'   re   _is_debug_build_cargo_args_uses_exec_bindingr.   Zrustc_flagsgetbasenameget_dylib_ext_pathrx   extendr[   rO   printsysrn   
subprocessPIPEcheck_outputCalledProcessErrorr   r   OSErrorr   metadata_find_cargo_artifacts
splitlinesr5   itemssplitnextStopIterationenviron_replace_cross_target_dirr\   len)r7   rQ   rb   rd   Z
rustc_cfgsrm   re   r#   Z
cargo_argsZ	rustflagscommandZ
rustc_argsZext_basenameZexisting_rustflagsZnew_rustflagsrn   cargo_messageser_   rs   	artifactsdestZartifact_pathr:   rz   r;   rX      s   



		



	

zbuild_rust.build_extensionr_   c              	   C  s$  |j d ur|j n| j}| j d ur| j n|}| jrd}tt| d}| j|_|D ]\}}|sBtjtj	tj|dd  d }|
 r||}t|\}}}td}	|	d ur_||	7 }tjtj|dd t|tr|}
|	d ury|
|	7 }
tj|j| jd}tj|dd tj||
}n||d	d
 | n| ||}tjtj|dd td|| t|| tjdkr|sg }|jt j!kr|"d n|jt j#kr|"d |r|$dd |"| zt%&|}W n
 t%j'y   Y nw t(|j)}||d@ d? O }t*|| q(d S )NFr      r   EXET)exist_okscriptsru   rv   z#Copying rust artifact from %s to %swin32z-xz-Sstripi$     )+r#   r!   r%   r   CommandBuildExtr@   r3   r   r   splitextr   get_ext_fullpath_split_platform_and_extension	sysconfigr   makedirsdirnamerA   r   rO   	build_libr>   Zinstall_scriptr   r   r   infoshutilcopyfiler   platformr   r   ZAllr[   ZDebuginsertr   r   r   statst_modechmod)r7   rQ   r_   Zdebug_buildr   module_nameZ
dylib_pathext_pathrG   exeZexecutable_nameZscripts_dirargsoutputmoder:   r:   r;   r]   .  sd   





zbuild_rust.install_extensionr`   c                 C  s0  | j d usJ tt| d}||}t|j|  r:t }|d ur:t	d}t
|ts.J |d t|  t  }d|v r@|S | j  dddd}|dsT|S g }d}	|dD ]}
|
dreq]|
 rl|	slq]d	}	||
 q]d|}t }|dd
d
 }|r||krt|\}}}||7 }|S )Nr   
EXT_SUFFIXz.abi3.rF   rG   ru   )linuxZ	manylinuxFTr   )r*   r   r   r@   r   _is_py_limited_apipy_limited_api_py_limited_apir   r   rA   rB   r   lowerrL   rW   r   rD   r[   rO   r   get_platformrsplitr   )r7   rQ   r`   r   r   Zabi3_suffixZso_extr*   Z
arch_partsZ
arch_founditemrh   Zhost_platformZ	host_archrG   	extensionr:   r:   r;   r   s  s<   



zbuild_rust.get_dylib_ext_path_PyLimitedApic                 C  sF   | j jddd}|d u rdS ddlm} t||}|  tt|jS )Nbdist_wheelF)creater   )r   )rJ   get_command_objZwheel.bdist_wheelr   r   ensure_finalizedr   r   )r7   r   ZCommandBdistWheelZbdist_wheel_commandr:   r:   r;   r     s   
zbuild_rust._py_limited_apic                 C  s>   | j d usJ |d ur|S t| j }|d ur|t kr|S d S N)r*   _adjusted_local_rust_targetr   )r7   rb   Zlocal_rust_targetr:   r:   r;   r     s   

zbuild_rust._detect_rust_targetboolc                 C  s4   | j rdS | jd ur| jS |jd ur|jS t| jS )NF)r%   r#   r   r!   )r7   rQ   r:   r:   r;   r     s   


zbuild_rust._is_debug_buildrd   r%   re   	List[str]c           	      C  s   g }|d ur| d|g |r| }|s|d |r"|d n| jr5dt| jd }|d|  h |jt||  d}|rN| dd	|g |j	d urY| |j	 |j
d urd| |j
 |S )
Nz--targetz	--releasez-qvr   rF   )r   z
--featuresri   )r   Zget_cargo_profiler[   verboseminfeatures_binding_featuresr   rO   r   Zcargo_manifest_args)	r7   rQ   rd   r%   re   r   ZprofileZverbose_levelr   r:   r:   r;   r     s0   


zbuild_rust._cargo_args)r+   r,   )r+   rB   )rQ   r   r+   r,   r   )rQ   r   rb   r)   r+   rc   )rQ   r   r_   rc   r+   r,   )rQ   r   r`   rB   r+   rB   )r+   r   )rb   r)   r+   r)   )rQ   r   r+   r   )
rQ   r   rd   r)   r%   r   re   r   r+   r   )__name__
__module____qualname____doc__descriptionuser_optionsboolean_optionsr*   __annotations__r0   r<   r=   ra   rX   r]   r   r   r   r   r   __classcell__r:   r:   r8   r;   r    "   s(   
 

	 
-
E
(

r    output_pathrB   input_pathsr   r+   r,   c           	      C  s   ddd| g|}z
t j|dd W d S  t jy+ } z|j}td|j|f d }~w tyq   zddlm} W n t	yD   t
d	w | }|D ]}t|d
}||  W d    n1 scw   Y  qJ||  Y d S w )NZlipoz-createz-outputT)ro   zlipo failed with code: %d
%sr   )	FatWriterzefailed to locate `lipo` or import `fat_macho.FatWriter`. Try installing with `pip install fat-macho` rb)r   r   r   r   r   
returncoder   Z	fat_machor   ImportErrorr   openaddreadwrite_to)	r   r   r   r   r   r   fatZ
input_pathfr:   r:   r;   rZ     s.   rZ   c                   @  s"   e Zd ZU dZded< ded< dS )r\   z
    Attributes:
        - module_name: dotted python import path of the module
        - path: the location the module has been installed at
    rB   r   r   N)r   r   r   r   r   r:   r:   r:   r;   r\   
  s   
 r\   r5   r)   c                 C  s,   |  d}t|dkrdS d|d< d|S )zoReplaces vendor in the target triple with unknown.

    Returns None if the target is not made of 4 parts.
    rF      Nunknownr   )r   r   rO   )r5   rP   r:   r:   r;   _replace_vendor_with_unknown  s
   

r   Dict[str, str]c               	   C  sZ   t jtj} t j }|t j| t j	ddt j	dtjt j	dtjd |S )zAPrepares environment variables to use when executing cargo build.PATHrV   PYTHON_SYS_EXECUTABLEPYO3_PYTHON)r   r   r   )
r3   r   r   r   
executabler   copyupdaterO   r   )Zbindirrm   r:   r:   r;   r   !  s   
r   ext_settingLiteral['auto', True, False]wheel_settingOptional[_PyLimitedApi]r   c                 C  s   | dkr| S t |S )a  Returns whether this extension is being built for the limited api.

    >>> _is_py_limited_api("auto", None)
    False

    >>> _is_py_limited_api("auto", True)
    True

    >>> _is_py_limited_api(True, False)
    True

    >>> _is_py_limited_api(False, True)
    False
    auto)r   )r   r   r:   r:   r;   r   8  s   r   rQ   r   r   r   Set[str]c                 C  s   | j tjtjfv rt S | j tju r8dh}| jdkr6t|tr/|dd  }|	d|  |S |r6|	d |S | j tj
u rBddhS td| j  d	)
Nzpyo3/extension-moduler   r   zpyo3/abi3-pyz	pyo3/abi3zcpython/python3-syszcpython/extension-modulezunknown Rust binding: 'r|   )Zbindingr   Z	NoBindingZExecsetZPyO3r   rA   rB   r   ZRustCPythonr   )rQ   r   r   python_versionr:   r:   r;   r   S  s   


r   )Zcp37Zcp38Zcp39Zcp310Zcp311Zcp312TFr*   c                 C  sb   | dkrt dddkrdS dS | dkr"t dddkr dS d	S | d
r/t dkr/dS dS )z}Returns the local rust target for the given `plat_name`, if it is
    necessary to 'force' a specific target for correctness.r   Nrf   Zgnuzi686-pc-windows-gnuzi686-pc-windows-msvcz	win-amd64zx86_64-pc-windows-gnuzx86_64-pc-windows-msvcrR   rS   rU   )r   r   rW   r   machine)r*   r:   r:   r;   r   k  s   r   r   Tuple[str, str, str]c                 C  s*   t j| \} }t j| \} }| ||fS )zSplits an extension path into a tuple (ext_path, plat_tag, extension).

    >>> _split_platform_and_extension("foo/bar.platform.so")
    ('foo/bar', '.platform', '.so')
    )r3   r   r   )r   r   Zplatform_tagr:   r:   r;   r     s   
r   r   rs   rt   c                C  sz   g }| D ]6}d|v r:||v r:t |}|ddkr:|d|kr:t|d d |d D ]\}}||v r9|| q,q|S )a  Identifies cargo artifacts built for the given `package_id` from the
    provided cargo_messages.

    >>> _find_cargo_artifacts(
    ...    [
    ...        '{"some_irrelevant_message": []}',
    ...        '{"reason":"compiler-artifact","package_id":"some_id","target":{"kind":["cdylib"]},"filenames":["/some/path/baz.so"]}',
    ...        '{"reason":"compiler-artifact","package_id":"some_id","target":{"kind":["dylib", "rlib"]},"filenames":["/file/two/baz.dylib", "/file/two/baz.rlib"]}',
    ...        '{"reason":"compiler-artifact","package_id":"some_other_id","target":{"kind":["cdylib"]},"filenames":["/not/this.so"]}',
    ...    ],
    ...    package_id="some_id",
    ...    kinds={"cdylib", "dylib"},
    ... )
    ['/some/path/baz.so', '/file/two/baz.dylib']
    >>> _find_cargo_artifacts(
    ...    [
    ...        '{"some_irrelevant_message": []}',
    ...        '{"reason":"compiler-artifact","package_id":"some_id","target":{"kind":["cdylib"]},"filenames":["/some/path/baz.so"]}',
    ...        '{"reason":"compiler-artifact","package_id":"some_id","target":{"kind":["cdylib", "rlib"]},"filenames":["/file/two/baz.dylib", "/file/two/baz.rlib"]}',
    ...        '{"reason":"compiler-artifact","package_id":"some_other_id","target":{"kind":["cdylib"]},"filenames":["/not/this.so"]}',
    ...    ],
    ...    package_id="some_id",
    ...    kinds={"rlib"},
    ... )
    ['/file/two/baz.rlib']
    zcompiler-artifactreasonrs   r5   kind	filenames)jsonloadsr   rY   r[   )r   rs   rt   r   messageparsedZartifact_kindfilenamer:   r:   r;   r     s    

r   r   re   c                C  s0   |j d|dd }|j d|dd }| ||S )a  Replaces target director from `cross` docker build with the correct
    local path.

    Cross artifact messages and metadata contain paths from inside the
    dockerfile; invoking `cargo metadata` we can work out the correct local
    target directory.
    r}   )r.   re   Ztarget_directoryr.   )Z	_metadatarL   )r   rQ   re   Zcross_target_dirZlocal_target_dirr:   r:   r;   r     s   r   )r   rB   r   r   r+   r,   )r5   rB   r+   r)   )r+   r   )r   r   r   r   r+   r   )rQ   r   r   r   r+   r   )r*   rB   r+   r)   )r   rB   r+   r   )r   r   rs   rB   rt   r   r+   r   )r   rB   rQ   r   re   r   r+   rB   )A
__future__r   globr  r3   r   r   r   r   r   	distutilsr   distutils.errorsr   r   r   r   distutils.sysconfigr   pathlibr	   typingr
   r   r   r   r   r   r   r   rH   Zsetuptools.command.buildr   r?   Zsetuptools.command.build_extr   r   r   typing_extensionsr   Z_utilsr   r   r   r   r   r   r   r   Z
rustc_infor   r   r   r    rZ   r\   r   r   r   r   r   r   r   r   r   r:   r:   r:   r;   <module>   sL    (   
S






2