3
]{                 @   s   d 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T ddlm	Z	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 ejdZdd ZG dd deZdS )zdistutils.command.build_ext

Implements the Distutils 'build_ext' command, for building extension
modules (currently limited to C extensions, should accommodate C++
extensions ASAP).    N)Command)*)customize_compilerget_python_version)get_config_h_filename)newer_group)	Extension)get_platform)log)	USER_BASEz3^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$c              C   s   ddl m}  |   d S )Nr   )show_compilers)distutils.ccompilerr   )r    r   1/usr/lib/python3.6/distutils/command/build_ext.pyr      s    r   c               @   s  e Zd ZdZdej Zd`dad	d
de  fdcddde fdddedfddde fdgdhdidjdkdldmdndodpgZdd%d(d1d8gZ	d:d2d;e
fgZd<d= Zd>d? Zd@dA ZdBdC ZdDdE ZdFdG ZdHdI ZdJdK ZdLdM ZejdNdO ZdPdQ ZdRdS ZdTdU ZdVdW ZdXdY ZdZd[ Zd\d] Zd^d_ Zd2S )q	build_extz8build C/C++ extensions (compile/link to build directory)z (separated by '%s')
build-lib=b(directory for compiled extension modulesbuild-temp=t1directory for temporary files (build by-products)z
plat-name=pz>platform name to cross-compile for, if supported (default: %s)inplaceiz=ignore build-lib and put compiled extensions into the source z,directory alongside your pure Python moduleszinclude-dirs=Iz.list of directories to search for header filesdefine=DC preprocessor macros to defineundef=U!C preprocessor macros to undefine
libraries=l!external C libraries to link withzlibrary-dirs=Lz.directories to search for external C librariesrpath=R7directories to search for shared C libraries at runtimelink-objects=O2extra explicit link objects to include in the linkdebugg'compile/link with debugging informationforcef2forcibly build everything (ignore file timestamps)	compiler=cspecify the compiler type	parallel=jnumber of parallel build jobsswig-cppN)make SWIG create C++ files (default is C)
swig-opts=!list of SWIG command line optionsswig=path to the SWIG executableuser#add user include, library and rpathzhelp-compilerzlist available compilersc             C   s   d | _ d | _d | _d | _d| _d | _d | _d | _d | _d | _	d | _
d | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d S )Nr   )
extensions	build_lib	plat_name
build_tempr   packageinclude_dirsdefineundef	librarieslibrary_dirsrpathlink_objectsr+   r.   compilerswigswig_cpp	swig_optsr=   parallel)selfr   r   r   initialize_optionsj   s*    zbuild_ext.initialize_optionsc       
      C   s  ddl m} | jdd(d)d*d+d,d-d. | jd kr8| jj| _| jj| _|j }|jdd}| j	d krn| jj	pjg | _	t
| j	tr| j	jtj| _	tjtjkr| j	jtjjtjd | j	j| ||kr| j	j| | jd | jd | jd k rg | _| jd krg | _nt
| jtr&| jjtj| _| jd kr:g | _nt
| jtrX| jjtj| _tjdkrT| jjtjjtjd tjtjkr| jjtjjtjd | jrtjj| jd| _ntjj| jd| _| j	jtjjt  ttdd }|r| jj| | j dkrd}n| j dd  }tjjtjd}|rHtjj||}| jj| tj!d d dks|tj!d d dkrtj"j#tjjtjdr| jjtjjtjddt$  d n| jjd d r |j%d!r |j&s| jj|j%d" n| jjd | j'r$| j'jd#}d$d% |D | _'| j(r:| j(jd#| _(| j)d krNg | _)n| j)jd&| _)| j*rtjjt+d}tjjt+d}	tjj,|r| j	j| tjj,|	r| jj|	 | jj|	 t
| j-tryt.| j-| _-W n t/k
r   t0d'Y nX d S )/Nr   )	sysconfigZbuildr@   rB   rK   r+   r.   rO   rA      )Zplat_specificZincluderG   rJ   ntZlibsZDebugZReleaseZ_homewin32   ZPCbuild   cygwinatheosbinlibZpythonZconfig.FPy_ENABLE_SHAREDZLIBDIR,c             S   s   g | ]}|d fqS )1r   ).0Zsymbolr   r   r   
<listcomp>   s    z.build_ext.finalize_options.<locals>.<listcomp> zparallel should be an integer)r@   r@   )rB   rB   )rK   rK   )r+   r+   )r.   r.   )rO   rO   )rA   rA   )1	distutilsrR   Zset_undefined_optionsrC   distributionZext_packageZext_modulesr?   Zget_python_incrD   
isinstancestrsplitospathsepsysexec_prefixbase_exec_prefixappendpathjoinZensure_string_listrG   rH   rI   nameprefixr+   rB   dirnamer   getattrrA   platform
executable
startswithr   get_config_varZpython_buildrE   rF   rN   r=   r   isdirrO   int
ValueErrorZDistutilsOptionError)
rP   rR   Z
py_includeZplat_py_includeZ	_sys_homesuffixZnew_libZdefinesZuser_includeZuser_libr   r   r   finalize_options   s    





(
zbuild_ext.finalize_optionsc             C   st  ddl m} | jsd S | jj rL| jd}| jj|j p:g  | j	j
|j || j| j| j| jd| _t| j tjdkr| jt kr| jj| j | jd k	r| jj| j | jd k	rx | jD ]\}}| jj|| qW | jd k	r x| jD ]}| jj| qW | jd k	r| jj| j | j	d k	r4| jj| j	 | jd k	rN| jj| j | j d k	rh| jj!| j  | j"  d S )Nr   )new_compiler
build_clib)rK   verbosedry_runr.   rT   )#r   r}   r?   rd   Zhas_c_librariesget_finalized_commandrG   extendZget_library_namesrH   rm   r~   rK   r   r   r.   r   rh   rp   rA   r	   Z
initializerD   Zset_include_dirsrE   Zdefine_macrorF   Zundefine_macroZset_librariesZset_library_dirsrI   Zset_runtime_library_dirsrJ   Zset_link_objectsbuild_extensions)rP   r}   r~   rp   valuemacror   r   r   run  s>    




zbuild_ext.runc       
      C   s  t |tstdxnt|D ]`\}}t |tr4qt |t sLt|dkrTtd|\}}tjd| t |t	ozt
j|stdt |tstdt||d }x*dD ]"}|j|}|dk	rt||| qW |jd|_d|k rtjd |jd}|rxg |_g |_xj|D ]b}	t |	to,t|	dks8tdt|	dkrX|jj|	d  nt|	dkr|jj|	 qW |||< qW dS )a  Ensure that the list of extensions (presumably provided as a
        command option 'extensions') is valid, i.e. it is a list of
        Extension objects.  We also support the old-style list of 2-tuples,
        where the tuples are (ext_name, build_info), which are converted to
        Extension instances here.

        Raise DistutilsSetupError if the structure is invalid anywhere;
        just returns otherwise.
        z:'ext_modules' option must be a list of Extension instances   zMeach element of 'ext_modules' option must be an Extension instance or 2-tuplezvold-style (ext_name, build_info) tuple found in ext_modules for extension '%s' -- please convert to Extension instancezRfirst element of each tuple in 'ext_modules' must be the extension name (a string)zOsecond element of each tuple in 'ext_modules' must be a dictionary (build info)sourcesrD   rH   rG   extra_objectsextra_compile_argsextra_link_argsNrI   Zdef_filez9'def_file' element of build info dict no longer supportedmacrosrS   z9'macros' element of build info dict must be 1- or 2-tupler   )rD   rH   rG   r   r   r   )rS   r   )re   listDistutilsSetupError	enumerater   tuplelenr
   warnrf   extension_name_rematchdictgetsetattrruntime_library_dirsdefine_macrosundef_macrosrm   )
rP   r?   r   extext_nameZ
build_infokeyvalr   r   r   r   r   check_extensions_listU  sT    





 




zbuild_ext.check_extensions_listc             C   s0   | j | j g }x| jD ]}|j|j qW |S )N)r   r?   r   r   )rP   	filenamesr   r   r   r   get_source_files  s
    zbuild_ext.get_source_filesc             C   s6   | j | j g }x | jD ]}|j| j|j qW |S )N)r   r?   rm   get_ext_fullpathrp   )rP   Zoutputsr   r   r   r   get_outputs  s
    zbuild_ext.get_outputsc             C   s(   | j | j | jr| j  n| j  d S )N)r   r?   rO   _build_extensions_parallel_build_extensions_serial)rP   r   r   r   r     s    
zbuild_ext.build_extensionsc                s   j }j dkrtj }yddlm} W n tk
r@   d }Y nX |d krVj  d S ||dT  fddjD }x6tj|D ]&\}}j	| |j
  W d Q R X qW W d Q R X d S )NTr   )ThreadPoolExecutor)Zmax_workersc                s   g | ]} j j|qS r   )Zsubmitbuild_extension)r`   r   )executorrP   r   r   ra     s   z8build_ext._build_extensions_parallel.<locals>.<listcomp>)rO   rh   	cpu_countZconcurrent.futuresr   ImportErrorr   r?   zip_filter_build_errorsresult)rP   Zworkersr   Zfuturesr   Zfutr   )r   rP   r   r     s     


z$build_ext._build_extensions_parallelc          
   C   s4   x.| j D ]$}| j| | j| W d Q R X qW d S )N)r?   r   r   )rP   r   r   r   r   r     s    z"build_ext._build_extensions_serialc             c   sT   y
d V  W nD t ttfk
rN } z"|js* | jd|j|f  W Y d d }~X nX d S )Nz"building extension "%s" failed: %s)ZCCompilerErrorZDistutilsErrorZCompileErrorZoptionalr   rp   )rP   r   er   r   r   r     s    
zbuild_ext._filter_build_errorsc       
      C   sX  |j }|d kst|ttf r,td|j t|}| j|j}||j }| jpZt	||dsnt
jd|j d S t
jd|j | j||}|jpg }|jd d  }x|jD ]}|j|f qW | jj|| j||j| j||jd}|d d  | _|jr |j|j |jp
g }|jp| jj|}	| jj||| j||j|j|| j || j| j|	d
 d S )Nzjin 'ext_modules' option (extension '%s'), 'sources' must be present and must be a list of source filenamesZnewerz$skipping '%s' extension (up-to-date)zbuilding '%s' extension)Z
output_dirr   rD   r+   extra_postargsdepends)rG   rH   r   r   export_symbolsr+   rB   Ztarget_lang)!r   re   r   r   r   rp   r   r   r.   r   r
   r+   infoswig_sourcesr   r   r   rm   rK   compilerB   rD   Z_built_objectsr   r   r   languageZdetect_languageZlink_shared_objectget_librariesrH   r   get_export_symbols)
rP   r   r   ext_pathr   Z
extra_argsr   rF   Zobjectsr   r   r   r   r     sN    



zbuild_ext.build_extensionc             C   s2  g }g }i }| j rtjd | j s6d| jks6d|jkr<d}nd}xX|D ]P}tjj|\}}	|	dkr|j|d |  |j| |d ||< qF|j| qFW |s|S | jp| j	 }
|
dg}|j
| j | j r|jd | jsx|jD ]}|j| qW x8|D ]0}|| }tjd	|| | j|d
||g   qW |S )zWalk the list of source files in 'sources', looking for SWIG
        interface (.i) files.  Run SWIG on all that are found, and
        return a modified 'sources' list with SWIG source files replaced
        by the generated C (or C++) files.
        z/--swig-cpp is deprecated - use --swig-opts=-c++z-c++z.cppz.cz.i_wraprS   z-pythonzswigging %s to %sz-o)rM   r
   r   rN   rh   rn   splitextrm   rL   	find_swigr   r   Zspawn)rP   r   	extensionZnew_sourcesr   Zswig_targetsZ
target_extsourcebaser   rL   Zswig_cmdotargetr   r   r   r   0  s>    





zbuild_ext.swig_sourcesc             C   s`   t jdkrdS t jdkrNxBdD ]&}t jjd| d}t jj|r|S qW dS ntd	t j d
S )zReturn the name of the SWIG executable.  On Unix, this is
        just "swig" -- it should be in the PATH.  Tries a bit harder on
        Windows.
        posixrL   rT   1.31.21.1z	c:\swig%szswig.exez>I don't know how to find (much less run) SWIG on platform '%s'N)r   r   r   )rh   rp   rn   ro   isfileZDistutilsPlatformError)rP   Zversfnr   r   r   r   f  s    


zbuild_ext.find_swigc             C   s   | j |}|jd}| j|d }| jsRtjj|dd |g  }tjj| j|S dj|dd }| jd}tjj	|j
|}tjj||S )	zReturns the path of the filename for a given extension.

        The file is located in `build_lib` or directly in the package
        (inplace option).
        r\   rS   Nr   build_pyr   r   r   )get_ext_fullnamerg   get_ext_filenamer   rh   rn   ro   r@   r   abspathZget_package_dir)rP   r   fullnameZmodpathfilenamerC   r   Zpackage_dirr   r   r   r   ~  s    


zbuild_ext.get_ext_fullpathc             C   s    | j dkr|S | j d | S dS )zSReturns the fullname of a given extension name.

        Adds the `package.` prefixNr\   )rC   )rP   r   r   r   r   r     s    
zbuild_ext.get_ext_fullnamec             C   s.   ddl m} |jd}|d}tjj| | S )zConvert the name of an extension (eg. "foo.bar") into the name
        of the file from which it will be loaded (eg. "foo/bar.so", or
        "foo\bar.pyd").
        r   )rw   r\   Z
EXT_SUFFIX)distutils.sysconfigrw   rg   rh   rn   ro   )rP   r   rw   r   Z
ext_suffixr   r   r   r     s    
zbuild_ext.get_ext_filenamec             C   s0   d|j jdd  }||jkr*|jj| |jS )a  Return the list of symbols that a shared extension has to
        export.  This either uses 'ext.export_symbols' or, if it's not
        provided, "PyInit_" + module_name.  Only relevant on Windows, where
        the .pyd file (DLL) must export the module "PyInit_" function.
        ZPyInit_r\   rS   r   )rp   rg   r   rm   )rP   r   Zinitfunc_namer   r   r   r     s    
zbuild_ext.get_export_symbolsc             C   s  t jdkrfddlm} t| j|s\d}| jr4|d }|t jd? t jd? d@ f }|j|g S |jS nXt jd	d
 dkrd}|t jd? t jd? d@ f }|j|g S t jd	d
 dkr>ddl	m
} d}|t jd? t jd? d@ f }g }xB|jdj D ]0}|jdr|j|dd	  n
|j|  qW |j|dg | S t jdkrP|jS t jd	d dkrj|jS ddl	m
} dr|jdrdjt jd? t jd? d@ |jd}|j|g S |jS d	S )zReturn the list of libraries to link against when building a
        shared extension.  On most platforms, this is just 'ext.libraries';
        on Windows, we add the Python library (eg. python20.dll).
        rU   r   )MSVCCompilerz
python%d%dZ_d         NrW   rX   zpython%d.%drY   )rR   ZSHLIBSz-lr   mdarwin   ZaixFr]   zpython{}.{}{}ZABIFLAGS)rj   rt   Zdistutils._msvccompilerr   re   rK   r+   
hexversionrG   rc   rR   rw   rg   rv   rm   format)rP   r   r   templateZ	pythonlibrR   Zextrar[   r   r   r   r     sJ    


zbuild_ext.get_libraries)r   r   r   )r   r   r   iignore build-lib and put compiled extensions into the source directory alongside your pure Python modules)r   r   r   )r   r   r   )r   r   r    )r!   r"   r#   )r%   r&   r'   )r(   r)   r*   )r+   r,   r-   )r.   r/   r0   )r1   r2   r3   )r4   r5   r6   )r7   Nr8   )r9   Nr:   )r;   Nr<   )r=   Nr>   ) __name__
__module____qualname__Zdescriptionrh   ri   Zsep_byr	   Zuser_optionsZboolean_optionsr   Zhelp_optionsrQ   r|   r   r   r   r   r   r   r   
contextlibcontextmanagerr   r   r   r   r   r   r   r   r   r   r   r   r   r   !   s   
                 
 @N	
K6	
r   )__doc__r   rh   rerj   Zdistutils.corer   Zdistutils.errorsr   r   r   r   Zdistutils.dep_utilr   Zdistutils.extensionr   Zdistutils.utilr	   rc   r
   Zsiter   r   r   r   r   r   r   r   r   <module>   s"   