o
    *ήcsP                     @   s  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m	Z	m
Z
 ddlmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZ ejdkrRdZnejdkrZd	Zned
ej dZ		d-ddZd.ddZ 		d/ddZ!		d0ddZ"d1ddZ#edfedfedfedfedfedfedfedfedfedfd
Z$d2ddZ%		d3ddZ&dd Z'd d! Z(d"d# Z)		d4d%d&Z*d'd( Z+d5d)d*Z,d6d+d,Z-dS )7    N)get_config_varget_config_varsget_path   )CCompilerRunnerCppCompilerRunnerFortranCompilerRunner)get_abspath	make_dirscopyGlobArbitraryDepthGlobglob_at_depthimport_module_from_filepyx_is_cplussha256_of_stringsha256_of_fileCompileErrorposixz.ontz.objzUnknown os.name: {}Fc                 K   sD  i }|dur9|  D ].\}}	t|tr!t|jD ]}
|	||
< qq
t|tr4t|j|D ]}
|	||
< q,q
|	||< q
|p<d}tj	
|sTtj	|rPtd|t| |du rgd}| D ]
}t||ddd q\g }| D ]4}|rxtj	|\}}ntj	tj	|\}}| }|||i  |t||fd|i| qk|S )aL   Compile source code files to object files.

    Parameters
    ==========

    files : iterable of str
        Paths to source files, if ``cwd`` is given, the paths are taken as relative.
    Runner: CompilerRunner subclass (optional)
        Could be e.g. ``FortranCompilerRunner``. Will be inferred from filename
        extensions if missing.
    destdir: str
        Output directory, if cwd is given, the path is taken as relative.
    cwd: str
        Working directory. Specify to have compiler run in other directory.
        also used as root of relative paths.
    keep_dir_struct: bool
        Reproduce directory structure in `destdir`. default: ``False``
    per_file_kwargs: dict
        Dict mapping instances in ``files`` to keyword arguments.
    \*\*kwargs: dict
        Default keyword arguments to pass to ``Runner``.

    N.z{} is not a directoryT)only_updatedest_is_dircwd)items
isinstancer   globpathnamer   r   filenameospathisdirexistsOSErrorformatr
   r   splitextbasenameupdategetappendsrc2obj)filesRunnerdestdirr   keep_dir_structper_file_kwargskwargs_per_file_kwargskvr    fdstpathsnameextfile_kwargs r9   O/tmp/pip-target-vg8gfxp4/lib/python/sympy/utilities/_compilation/compilation.pycompile_sources   s<   




r;   c                 C   sn   | pt jdd} |  dkr"|rtdddgi| fS tddgi| fS |  dks(|r2tdd	gi| fS ti | fS )
NSYMPY_COMPILER_VENDORgnuintelflagsz-nofor_mainz-cxxlibllvmlib_optionsfortran)r   environr(   lowerr   r   
ValueErrorvendorcplusr   r9   r9   r:   get_mixed_fort_c_linker]   s"   

rI   c                 K   s  |du rt jt j| d \}}|r|td7 }|sM|rFt|dd||d\}}	}
|	 D ]\}}||v r@|| | q0|||< q0n|rKt	}nt
}|dg }|r^d|vr^|d |dd	}|sjtd
t||d}|| ||fd|i|}|  |S )aK   Link object files.

    Parameters
    ==========

    obj_files: iterable of str
        Paths to object files.
    out_file: str (optional)
        Path to executable/shared library, if ``None`` it will be
        deduced from the last item in obj_files.
    shared: bool
        Generate a shared library?
    Runner: CompilerRunner subclass (optional)
        If not given the ``cplus`` and ``fort`` flags will be inspected
        (fallback is the C compiler).
    cwd: str
        Path to the root of relative paths and working directory for compiler.
    cplus: bool
        C++ objects? default: ``False``.
    fort: bool
        Fortran objects? default: ``False``.
    \*\*kwargs: dict
        Keyword arguments passed to ``Runner``.

    Returns
    =======

    The absolute path to the generated shared object / executable.

    N
EXT_SUFFIXrG   rF   r?   z-shared
run_linkerTz*run_linker was set to False (nonsensical).r   r   )r   r    r%   r&   r   rI   r(   r   expandr   r   popr)   rE   r	   run)	obj_filesout_filesharedr,   r   rH   fortr0   r7   extra_kwargsrG   r2   r3   r?   rL   runnerr9   r9   r:   linkr   s>    


rW   c                 K   s  |pg }| dg }| dg }tjdkrtd nDtjdkr!n>tjdd dkr+n4td	r^t }	|d
g |	d g |d
< ||	d g7 }|	d  D ]}
|
	dr\||
dd g7 }qLn	 | dg }d}|D ]}||vrt|
| qit| fd|||||||d|S )a,   Link Python extension module (shared object) for importing

    Parameters
    ==========

    obj_files: iterable of str
        Paths to object files to be linked.
    so_file: str
        Name (path) of shared object file to create. If not specified it will
        have the basname of the last object file in `obj_files` but with the
        extension '.so' (Unix).
    cwd: path string
        Root of relative paths and working directory of linker.
    libraries: iterable of strings
        Libraries to link against, e.g. ['m'].
    cplus: bool
        Any C++ objects? default: ``False``.
    fort: bool
        Any Fortran objects? default: ``False``.
    kwargs**: dict
        Keyword arguments passed to ``link(...)``.

    Returns
    =======

    Absolute path to the generate shared object.
    include_dirslibrary_dirswin32zWindows not yet supported.darwinN   aixPy_ENABLE_SHAREDlinkline
PY_LDFLAGSLIBDIR
BLDLIBRARYz-l   r?   )-pthreadT)rS   r?   r   rH   rT   rX   	librariesrY   )rO   sysplatformwarningswarnr   r   r(   split
startswithr)   rW   )rQ   so_filer   re   rH   rT   r0   rX   rY   cfgDictoptr?   needed_flagsflagr9   r9   r:   
link_py_so   s>   



rq   c              	   K   sl  ddl m}m} ddl m} |  ds|  dsJ |p!d}|p%d}|ddr.d	nd
}tj	tj
| d | }tj||}	|rLt }
nd}
t| z\||}|j| d|vrgd|jd< || g|}|jdkrvtdtjtj| tj|krtj|	rt|	 ttjtj| || W t|
 |	S W t|
 |	S t|
 w )a   Generates a C file from a Cython source file.

    Parameters
    ==========

    src: str
        Path to Cython source.
    destdir: str (optional)
        Path to output directory (default: '.').
    cwd: path string (optional)
        Root of relative paths (default: '.').
    **cy_kwargs:
        Second argument passed to cy_compile. Generates a .cpp file if ``cplus=True`` in ``cy_kwargs``,
        else a .c file.
    r   )default_optionsCompilationOptions)compile.pyxz.pyr   rH   F.cpp.clanguage_levelr\   zCython compilation failed.)Cython.Compiler.Mainrr   rs   rt   rD   endswithr(   r   r    r%   r&   joingetcwdchdir__dict__r'   
num_errorsrE   abspathdirnamer"   unlinkshutilmove)srcr-   r   	cy_kwargsrr   rs   
cy_compiler7   c_namedstfileori_dir
cy_options	cy_resultr9   r9   r:   simple_cythonize   s<    



 
 

r   f95f2003f2008)
rw   rv   z.cxxz.fz.forz.ftnz.f90z.f95z.f03z.f08c                 K   sH  t jt j| \}}|du r#t j| rd}n
t j| }|p"d}t j|r2t j||t }|	dg }|rGt
d}	|	|vrG||	 | dkrYt| f|||d|S |du rmt|  \}}
d|vrm|
|d< |	dg }d	}|D ]}||vr|| qw|	d
d}|rtd|| g|f||||d|}|  |S )a   Compiles a source code file to an object file.

    Files ending with '.pyx' assumed to be cython files and
    are dispatched to pyx2obj.

    Parameters
    ==========

    srcpath: str
        Path to source file.
    Runner: CompilerRunner subclass (optional)
        If ``None``: deduced from extension of srcpath.
    objpath : str (optional)
        Path to generated object. If ``None``: deduced from ``srcpath``.
    cwd: str (optional)
        Working directory and root of relative paths. If ``None``: current dir.
    inc_py: bool
        Add Python include path to kwarg "include_dirs". Default: False
    \*\*kwargs: dict
        keyword arguments passed to Runner or pyx2obj

    Nr   rX   includeru   )objpathrX   r   stdr?   )-fPICrL   Fz#src2obj called with run_linker=True)rX   rL   r   r?   )r   r    r%   r&   isabsr   r!   r{   objextrO   r   r)   rD   pyx2objextension_mappingr   rP   )srcpathr,   r   r   inc_pyr0   r6   r7   rX   
py_inc_dirr   r?   ro   rp   rL   rV   r9   r9   r:   r*   =  sJ   

r*   c                 K   sF  |  dsJ |p
d}|pd}|ptj|}t||d}tj|r:tj| }	tj|	\}
}tj||
t	 }|p=i }||d< |du rJt
| }||d< t| f||d|}|p\g }|dg }d	}|D ]}||vrr|| qg|d
g }|ddrtd|r|dd}n|dd}t|f||||||ddd|S )a9  
    Convenience function

    If cwd is specified, pyxpath and dst are taken to be relative
    If only_update is set to `True` the modification time is checked
    and compilation is only run if the source is newer than the
    destination

    Parameters
    ==========

    pyxpath: str
        Path to Cython source file.
    objpath: str (optional)
        Path to object file to generate.
    destdir: str (optional)
        Directory to put generated C file. When ``None``: directory of ``objpath``.
    cwd: str (optional)
        Working directory and root of relative paths.
    include_dirs: iterable of path strings (optional)
        Passed onto src2obj and via cy_kwargs['include_path']
        to simple_cythonize.
    cy_kwargs: dict (optional)
        Keyword arguments passed onto `simple_cythonize`
    cplus: bool (optional)
        Indicate whether C++ is used. default: auto-detect using ``.util.pyx_is_cplus``.
    compile_kwargs: dict
        keyword arguments passed onto src2obj

    Returns
    =======

    Absolute path of generated object file.

    ru   r   rM   
output_dirNrH   r-   r   r?   )z-fwrapvrd   r   optionsstrict_aliasingFz/Cython requires strict aliasing to be disabled.r   zc++98c99T)r   r   rX   r?   r   r   r   r   )rz   r   r    r   r	   r!   r&   r%   r{   r   r   r   rO   r)   r   r*   )pyxpathr   r-   r   rX   r   rH   r0   abs_objpath	pyx_fnamer6   r7   interm_c_filer?   ro   rp   r   r   r9   r9   r:   r     sD   %

r   c                 C   sD   | D ]}t j|\}}| }|tv rt| d |kr dS qdS )Nr   TF)r   r    r%   rD   r   )srcsclsr   r6   r7   keyr9   r9   r:   _any_X  s   r   c                 C   
   t | tS N)r   r   r   r9   r9   r:   any_fortran_src     
r   c                 C   r   r   )r   r   r   r9   r9   r:   any_cplus_src  r   r   r   c              	   C   s   |du rt jt j| d d }|pi }|pi }ztt j||| }W |S  tyU   ttt	t
| f||d|}t|f|t| t| d|}t|}Y |S w )a   Compiles sources to a shared object (Python extension) and imports it

    Sources in ``sources`` which is imported. If shared object is newer than the sources, they
    are not recompiled but instead it is imported.

    Parameters
    ==========

    sources : string
        List of paths to sources.
    extname : string
        Name of extension (default: ``None``).
        If ``None``: taken from the last file in ``sources`` without extension.
    build_dir: str
        Path to directory in which objects files etc. are generated.
    compile_kwargs: dict
        keyword arguments passed to ``compile_sources``
    link_kwargs: dict
        keyword arguments passed to ``link_py_so``

    Returns
    =======

    The imported module from of the Python extension.
    NrJ   r   r   r   rT   rH   )r   r    r%   r&   r   r{   ImportErrorr;   listmapr	   rq   r   r   )sourcesextname	build_dircompile_kwargslink_kwargsmodobjssor9   r9   r:   compile_link_import_py_ext  s*   
r   c           
   	   C   s@  |pt  }tj|std|g }| D ]\}}tj||}d}t|d	 }tj
|r^tj
|d rTt|d }| }	W d    n1 sNw   Y  nt|	 }	|	|k}|rt|d}|| W d    n1 suw   Y  t|d d}|| W d    n1 sw   Y  || q||fS )NzNon-existent directory: Tutf-8z.sha256wt)tempfilemkdtempr   r    r!   r#   r{   r   encode	hexdigestr"   openreadr   writer)   )
r   r   source_filesr6   r   destdifferssha256_in_memfhsha256_on_diskr9   r9   r:   _write_sources_to_build_dir  s2   

r   c                 K   s4   t | |\}}t|fd|i|}t|d}||fS )a   Compiles, links and imports extension module from source.

    Parameters
    ==========

    sources : iterable of name/source pair tuples
    build_dir : string (default: None)
        Path. ``None`` implies use a temporary directory.
    **kwargs:
        Keyword arguments passed onto `compile_link_import_py_ext`.

    Returns
    =======

    mod : module
        The compiled and imported extension module.
    info : dict
        Containing ``build_dir`` as 'build_dir'.

    r   )r   )r   r   dict)r   r   r0   r   r   infor9   r9   r:   compile_link_import_strings)  s   
r   c              	   C   s   |r
|dur
t dzVt| |\}}tttt|f||d|p!i }t|f|t|t|d|p3i }t	j
|gt	jt	jd}| }	dd | D \}
}W |r`tj|r`t| d}n|rptj|rpt| d}w t|	|d}|
|f|fS )	ay   Compiles, links and runs a program built from sources.

    Parameters
    ==========

    sources : iterable of name/source pair tuples
    build_dir : string (default: None)
        Path. ``None`` implies use a temporary directory.
    clean : bool
        Whether to remove build_dir after use. This will only have an
        effect if ``build_dir`` is ``None`` (which creates a temporary directory).
        Passing ``clean == True`` and ``build_dir != None`` raises a ``ValueError``.
        This will also set ``build_dir`` in returned info dictionary to ``None``.
    compile_kwargs: dict
        Keyword arguments passed onto ``compile_sources``
    link_kwargs: dict
        Keyword arguments passed onto ``link``

    Returns
    =======

    (stdout, stderr): pair of strings
    info: dict
        Containing exit status as 'exit_status' and ``build_dir`` as 'build_dir'

    NzIAutomatic removal of build_dir is only available for temporary directory.r   r   )stdoutstderrc                 S   s   g | ]}| d qS )r   )decode).0txtr9   r9   r:   
<listcomp>j  s    z'compile_run_strings.<locals>.<listcomp>)exit_statusr   )rE   r   r;   r   r   r	   rW   r   r   
subprocessPopenPIPEwaitcommunicater   r    r!   r   rmtreer   )r   r   cleanr   r   r   r   progpr   r   r   r   r9   r9   r:   compile_run_stringsD  s6   

r   )NNNFN)NFN)NFNNFF)NNNFF)NN)NNNF)NNNNNN)Nr   NNr   )NFNN).r   r   r   r   rf   r   rh   	sysconfigr   r   r   runnersr   r   r   utilr	   r
   r   r   r   r   r   r   r   r   r   r6   r   ri   r$   r;   rI   rW   rq   r   r   r*   r   r   r   r   r   r   r   r   r9   r9   r9   r:   <module>   sf    4



?
F

A7
B
Q

,
