U
    X	aXj                     @   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mZ d dlmZ d dl	m
Z
mZmZmZmZ d dlmZmZmZmZmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZm Z m!Z!m"Z"m#Z# d dl$Z$da%e$& Z'e( Z)dd Z*dd Z+dd Z,e+ede, dKddZ-e+ede- dLddZ.e+ede. dMddZ/e+ede/ dNddZ0e+ede0 d d! Z1d"d# Z2e+ed$e2 dOd%d&Z3e+ed'e3 dPd)d*Z4d+d gfd,d-Z5e+ed.e5 d/d0 Z6e+ed1e6 d2e
d3< d4e
d5< d6e
d7< d8e
d9< d:e
d;< d<e
d=< e j7d>7  _7ej8d?krBd@e
dA< e! rBe9dB dCej7 e_7eZ:dQdDdEZee_eZ;dFdG Zee_dHD ]0Z<ej=>dIe< dJ Z?e?dk	rle@e?dGe qldS )R    N)copy)	ccompiler)compiler_classgen_lib_optionsget_default_compilernew_compiler	CCompiler)DistutilsExecErrorDistutilsModuleErrorDistutilsPlatformErrorCompileErrorUnknownFileError)customize_compiler)LooseVersion)log)filepath_from_subprocess_outputforward_bytes_to_stdout)	cyg2win32is_sequencemingw32get_num_build_jobs_commandline_dep_stringc              	   C   s   | d }t j|sdS t|d}| }W 5 Q R X t|||}|d }||krVdS d|dd }	dd tj|	dd	D }
z2t 	| j
}|
D ]}t 	|j
|kr W dS qW n tk
r   Y dS X d
S )z
    Check if an objects needs to be rebuild based on its dependencies

    Parameters
    ----------
    obj : str
        object file

    Returns
    -------
    bool
    .dTr Nc                 S   s"   g | ]}|d kr| ds|qS )
:)endswith).0x r!   =/tmp/pip-unpacked-wheel-zbzmve17/numpy/distutils/ccompiler.py
<listcomp>D   s     
z _needs_build.<locals>.<listcomp>)posixF)ospathexistsopen	readlinesr   joinshlexsplitstatst_mtimeOSError)objcc_argsextra_postargspp_optsZdep_fileflinesZcmdlineZlast_cmdlinecontentsdepsZt_objr!   r!   r"   _needs_build$   s&    r8   c                    s    fdd}t | || d S )Nc                    s    | f||S Nr!   )selfargskwfuncr!   r"   <lambda>X       z replace_method.<locals>.<lambda>)setattr)klassmethod_namer>   mr!   r=   r"   replace_methodV   s    rE   c                 C   s   dS )z
    Does nothing here, but is called by the get_version method and can be
    overridden by subclasses. In particular it is redefined in the `FCompiler`
    class where more documentation can be found.

    Nr!   r:   r!   r!   r"   CCompiler_find_executablesa   s    rG   find_executablesc              
   C   s   |dkr"|}t |r"dt|}t| z&| jr@t| ntj|tjd W nJ tj	k
r } z|j
}|j}W 5 d}~X Y n  tk
r   d}d}Y nX dS t |rdt|}| jrt| td|rd}nd}td	|||f dS )
a  
    Execute a command in a sub-process.

    Parameters
    ----------
    cmd : str
        The command to execute.
    display : str or sequence of str, optional
        The text to add to the log file kept by `numpy.distutils`.
        If not given, `display` is equal to `cmd`.

    Returns
    -------
    None

    Raises
    ------
    DistutilsExecError
        If the command failed, i.e. the exit status was not 0.

    N stderrr@      s   Too many open filesz2
Try rerunning setup command until build succeeds.r   z)Command "%s" failed with exit status %d%s)r   r*   listr   infoverbose
subprocesscheck_outputSTDOUTCalledProcessErroroutput
returncoder/   r   researchr	   )r:   cmddisplayexcosmsgr!   r!   r"   CCompiler_spawno   s4    

r^   spawnr   c                 C   s   |dkrd}g }|D ]}t jt j|\}}t j|d }|t j|d }|dr|dd }|d| }	t jt j	|	}	|	||d  }|| j
krtd||f |rt j|}t j||| j }
||
 q|S )a  
    Return the name of the object files for the given source files.

    Parameters
    ----------
    source_filenames : list of str
        The list of paths to source files. Paths can be either relative or
        absolute, this is handled transparently.
    strip_dir : bool, optional
        Whether to strip the directory from the returned paths. If True,
        the file name prepended by `output_dir` is returned. Default is False.
    output_dir : str, optional
        If given, this path is prepended to the returned paths to the
        object files.

    Returns
    -------
    obj_names : list of str
        The list of paths to the object files corresponding to the source
        files in `source_filenames`.

    Nr      z..   z"unknown file type '%s' (from '%s'))r%   r&   splitextnormpath
splitdriveisabs
startswithrfindbasenameabspathZsrc_extensionsr   r*   Zobj_extensionappend)r:   Zsource_filenamesZ	strip_dir
output_dirZ	obj_namessrc_namebaseextidZobj_namer!   r!   r"   CCompiler_object_filenames   s&    

rq   Zobject_filenamesc	              	      s<  t  }	t tdkrt|	aW 5 Q R X |s0g S ddlm}
m}m} t	|
rg }dD ]4}t
d| }|dkrrqV|d|d|f  qVd|}nj}d	d|f }t| |||||\}}}|| d
d  }r
|dd 7 }t|  fdd}t	|
rt| }g g  }}|D ]r}||krL|| \}}jdkrt|}t|}||r||s||||ff n||||ff qL|}|D ]}|| qn| }t|dkr$|	dkr$ddl}|j|	}||| |  n|D ]}|| q(|S )a  
    Compile one or more source files.

    Please refer to the Python distutils API reference for more details.

    Parameters
    ----------
    sources : list of str
        A list of filenames
    output_dir : str, optional
        Path to the output directory.
    macros : list of tuples
        A list of macro definitions.
    include_dirs : list of str, optional
        The directories to add to the default include file search path for
        this compilation only.
    debug : bool, optional
        Whether or not to output debug symbols in or alongside the object
        file(s).
    extra_preargs, extra_postargs : ?
        Extra pre- and post-arguments.
    depends : list of str, optional
        A list of file names that all targets depend on.

    Returns
    -------
    objects : list of str
        A list of object file names, one per source file `sources`.

    Raises
    ------
    CompileError
        If compilation fails.

    Nr   )	FCompiler	is_f_filehas_f90_header)Zf77Zf90ZfixZ	compiler_zFortran %s compiler: %srI   r   zC compiler: %s
zcompile options: '%s'z
extra options: '%s'c                    s   | \}\}}t | sd S t$ |tkrBt| W 5 Q R  qXW 5 Q R X td qz(t |||  W 5 Q R X W 5 t t| W 5 Q R X X d S )Ng?)	r8   _global_lock_processing_filesaddtimesleepremove_job_semaphore_compile)r;   r0   srcrn   r1   r2   r3   r:   r!   r"   single_compile+  s    
"z)CCompiler_compile.<locals>.single_compileZabsoftr`   )r   ru   r{   	threading	SemaphoreZnumpy.distutils.fcompilerrr   rs   rt   
isinstancegetattrrj   r*   compiler_sor   rN   Z_setup_compileZ_get_cc_argsrM   keyscompiler_typer   itemslenZmultiprocessing.poolpoolZ
ThreadPoolmapclose)r:   sourcesrk   macrosinclude_dirsdebugextra_preargsr2   dependsjobsrr   rs   rt   rY   ZfcZfcompZccompZobjectsbuildr   Zobjects_to_buildZf77_objectsZother_objectsr0   r}   rn   Zbuild_itemsr[   multiprocessingr   r!   r~   r"   CCompiler_compile   sj    +

 



r   compiler!   c                    s  t d| jj jjf  t| dr>d| jd kr>| jd  fdd}|dr`|  j |d	r j	D ]\}}| 
|| qn|d
r jD ]}| | q|dr| | j j  |dr| | j j  |dr|  j |dr|  j dS )a  
    Customize compiler using distutils command.

    Parameters
    ----------
    cmd : class instance
        An instance inheriting from `distutils.cmd.Command`.
    ignore : sequence of str, optional
        List of `CCompiler` commands (without ``'set_'``) that should not be
        altered. Strings that are checked for are:
        ``('include_dirs', 'define', 'undef', 'libraries', 'library_dirs',
        'rpath', 'link_objects')``.

    Returns
    -------
    None

    zcustomize %s using %scompilerclangr   z-ffp-exception-behavior=strictc                    s   t  | d d k	o| kS r9   )r   )attrrX   ignorer!   r"   allow  s    z&CCompiler_customize_cmd.<locals>.allowr   defineundef	librarieslibrary_dirsrpathlink_objectsN)r   rN   	__class____name__hasattrr   rj   Zset_include_dirsr   r   Zdefine_macror   Zundefine_macroZset_librariesr   Zset_library_dirsr   Zset_runtime_library_dirsr   Zset_link_objectsr   )r:   rX   r   r   namevaluemacror!   r   r"   CCompiler_customize_cmdn  s,    
r   Zcustomize_cmdc                    s   g }d}t | j }dD ]}||kr|| q|D ]8}t| |r6t| |}t|t|}||t|f q6dt|d  d   fdd|D }d	|S )	Nr   )
versionr   r   Zobject_switchZcompile_switchr   r   r   r   r   z%-r`   zs = %sc                    s   g | ]} | qS r!   r!   )r   propfmtr!   r"   r#     s     z'_compiler_to_string.<locals>.<listcomp>r   )
rM   Zexecutablesr   rj   r   r   maxr   reprr*   )r   propsZmxr   keyvr5   r!   r   r"   _compiler_to_string  s    

r   c                 C   sX   z|    W n tk
r    Y nX tjjdk rTtd t| j tt|  td dS )z
    Print the compiler customizations to stdout.

    Parameters
    ----------
    None

    Returns
    -------
    None

    Notes
    -----
    Printing is only done if the distutils log threshold is < 2.

    ra   zP********************************************************************************N)get_version	Exceptionr   _global_log	thresholdprintr   r   rF   r!   r!   r"   CCompiler_show_customization  s    
r   Zshow_customizationc           
   	   C   s  t d| jj  t|  |rz| jd W n ttfk
rF   Y nX t	| drd| j
d kr| js| j
d drd\}}nd\}}| j
d ||g| j
d	d
  | _n8t	| drt d| j
f  t	| dst d| jj  t	| dr*d| j
d ks"d| j
d ks"d| j
d kr*d| _ntjdkrdd
l}dd
l}| }zvzTtj|d}t|d}	|	d W 5 Q R X | j|g|dd|d gd d| _W n tk
r   d| _Y nX W 5 || X d
S )am  
    Do any platform-specific customization of a compiler instance.

    This method calls `distutils.sysconfig.customize_compiler` for
    platform-specific customization, as well as optionally remove a flag
    to suppress spurious warnings in case C++ code is being compiled.

    Parameters
    ----------
    dist : object
        This parameter is not used for anything.
    need_cxx : bool, optional
        Whether or not C++ has to be compiled. If so (True), the
        ``"-Wstrict-prototypes"`` option is removed to prevent spurious
        warnings. Default is False.

    Returns
    -------
    None

    Notes
    -----
    All the default options used by distutils can be extracted with::

      from distutils import sysconfig
      sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
                                'CCSHARED', 'LDSHARED', 'SO')

    zcustomize %sz-Wstrict-prototypesr   ccr   gcc)r   g++)r   zc++r`   Nz#### %s #######compiler_cxxzMissing compiler_cxx fix for r   r   Tr$   zfile.cwzint a;
z-MMDz-MFr   )rk   r   F)r   rN   r   r   r   r   rz   AttributeError
ValueErrorr   r   r   rf   replacewarnZ_auto_dependsr%   r   tempfileshutilmkdtemprmtreer&   r*   r(   writer   r   )
r:   distZneed_cxxabr   r   Ztmpdirfnr4   r!   r!   r"   CCompiler_customize  sR    




r   Z	customize[-.\d]+c                    s    fdd}|S )aU  
    Simple matching of version numbers, for use in CCompiler and FCompiler.

    Parameters
    ----------
    pat : str, optional
        A regular expression matching version numbers.
        Default is ``r'[-.\d]+'``.
    ignore : str, optional
        A regular expression matching patterns to skip.
        Default is ``''``, in which case nothing is skipped.
    start : str, optional
        A regular expression matching the start of where to start looking
        for version numbers.
        Default is ``''``, in which case searching is started at the
        beginning of the version string given to `matcher`.

    Returns
    -------
    matcher : callable
        A function that is appropriate to use as the ``.version_match``
        attribute of a `CCompiler` class. `matcher` takes a single parameter,
        a version string.

    c                    sz   | dd}d}r0t|}|s(d S | }t||d  }|sLd S  rpt |drp| }q0qpq0|dS )Nr   rI   r   )r   rV   matchendrW   group)r:   version_stringposrD   r   patstartr!   r"   matcher;  s    z%simple_version_match.<locals>.matcherr!   )r   r   r   r   r!   r   r"   simple_version_match!  s    r   Fc           	         s:  |st | dr| jS |   z
| j}W n tk
r<   Y dS X |rJ|d sNdS z
| j}W nD tk
r   z
| j W n tk
r   Y Y dS X  fdd}Y nX ztj|tj	d}W nL tj
k
r } z|j}|j}W 5 d}~X Y n* tk
 r   d}d}Y nX t|}d}d}||kr0||}|r0t|}|| _|S )	a  
    Return compiler version, or None if compiler is not available.

    Parameters
    ----------
    force : bool, optional
        If True, force a new determination of the version, even if the
        compiler already has a version attribute. Default is False.
    ok_status : list of int, optional
        The list of status values returned by the version look-up process
        for which a version string is returned. If the status value is not
        in `ok_status`, None is returned. Default is ``[0]``.

    Returns
    -------
    version : str or None
        Version string, in the format of `distutils.version.LooseVersion`.

    r   Nr   c                    s"   t  | }|sd S |d}|S )Nr   )rV   r   r   )r   rD   r   r   r!   r"   r   t  s
    
z&CCompiler_get_version.<locals>.matcherrJ   rL   r@   )r   r   rH   version_cmdr   Zversion_matchZversion_patternrP   rQ   rR   rS   rT   rU   r/   r   r   )	r:   forceZ	ok_statusr   r   rT   rZ   statusr   r!   r   r"   CCompiler_get_versionP  sD    





r   r   c                 C   s   | j dkr| S t| }|jd g|jdd  |_tjdrrd|jd krr|jd |jd g|jdd  |_n|jd g|jdd  |_|S )z
    Return the C++ compiler.

    Parameters
    ----------
    None

    Returns
    -------
    cxx : class instance
        The C++ compiler, as a `CCompiler` instance.

    )msvcintelwintelemwr   r`   NaixZ	ld_so_aixra   )r   r   r   r   sysplatformrf   	linker_so)r:   cxxr!   r!   r"   CCompiler_cxx_compiler  s    
r   Zcxx_compiler)intelccompilerZIntelCCompilerz(Intel C Compiler for 32-bit applicationsintel)r   ZIntelItaniumCCompilerz7Intel C Itanium Compiler for Itanium-based applicationsintele)r   ZIntelEM64TCCompilerz(Intel C Compiler for 64-bit applicationsintelem)r   ZIntelCCompilerWz3Intel C Compiler for 32-bit applications on Windowsr   )r   ZIntelEM64TCCompilerWz3Intel C Compiler for 64-bit applications on Windowsr   )ZpathccompilerZPathScaleCCompilerz2PathScale Compiler for SiCortex-based applicationspathcc))linux.*r   )r   r   )r   r   )r   r   )ntr   )r   r   win32)Zmingw32ccompilerZMingw32CCompilerz>Mingw32 port of GNU C Compiler for Win32(for MSC built Python)r   z+Setting mingw32 as default compiler for nt.))r   r   c                 C   s  |d krt  t jk}| d kr$tj} z"|d kr6t| }t| \}}}W n8 tk
r~   d|  }|d k	rr|d|  }t|Y nX d| }zt	| W n t
k
r" }	 znt|	}t dt| |dd  }zt	| W n8 t
k
r }	 zt|	}td| W 5 d }	~	X Y nX W 5 d }	~	X Y nX ztj| }
t|
| }W n& tk
rd   td||f Y nX |d ||}||_t d|  |S )	Nz5don't know how to compile C/C++ code on platform '%s'z with '%s' compilerznumpy.distutils.z,%s in numpy.distutils; trying from distutils   z4can't compile C/C++ code: unable to load module '%s'zBcan't compile C/C++ code: unable to find class '%s' in module '%s'znew_compiler returns %s)r   Zget_thresholdINFOr%   r   r   r   KeyErrorr   
__import__ImportErrorstrrN   r
   r   modulesvarsrO   r   )platr   rO   dry_runr   module_name
class_namelong_descriptionr]   emodulerB   r!   r!   r"   r     sP    *
r   c                 C   sB   t | |||}g }|D ]&}t|r2|t| q|| q|S r9   )_distutils_gen_lib_optionsr   extendrM   rj   )r   r   runtime_library_dirsr   r   Zlib_optsro   r!   r!   r"   r     s     r   )Zmsvc9r   Z_msvcZbcppZcygwincZemxcZunixcz
distutils.r   )N)r   r   )NNNr   NNN)r!   )r   )r   r   r   )NNNr   r   )Ar%   rV   r   r+   rx   rP   r   	distutilsr   distutils.ccompilerr   r   r   r   r   distutils.errorsr	   r
   r   r   r   distutils.sysconfigr   Zdistutils.versionr   Znumpy.distutilsr   Znumpy.distutils.exec_commandr   r   Znumpy.distutils.misc_utilr   r   r   r   r   r   r{   Lockru   setrv   r8   rE   rG   r^   rq   r   r   r   r   r   r   r   r   Z_default_compilersr   rN   Z_distutils_new_compilerr   Z_ccr   get_mrA   r!   r!   r!   r"   <module>   s   2

?
-         
 
/
Q
/C
     
,
