B
    â‹d%  ã               @   s¦   d 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 ddlmZ ejZdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Zefdd„Zdd„ ZdS )zÙ
This module provides a simple interface for loading a shared library via ctypes,
allowing it to be specified in an OS-independent way and searched for preferentially
according to the paths that pkg-config specifies.
é    N)Úfind_library)Údeque)Ú	getoutputc             C   sÔ   g }g }g }x8| D ]0}t  d| ¡dkr*qtd |¡ƒ t d¡ qW t| ƒdkrÊxvtdd | ¡ ƒ 	¡ D ]\}| 
d¡rŒ| |dd	… ¡ qj| 
d
¡rª| |dd	… ¡ qj| 
d¡rj| |dd	… ¡ qjW |||fS )a  Use pkg-config to query for the location of libraries, library directories,
       and header directories

       Arguments:
           pkg_libries(list): A list of packages as strings

       Returns:
           libraries(list), library_dirs(list), include_dirs(list)
    z"pkg-config --exists %s 2>/dev/nullr   zCould not find library {0}é   z>PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config --libs --cflags %sú z-lé   Nz-Lz-I)ÚosÚsystemÚprintÚformatÚsysÚexitÚlenr   ÚjoinÚsplitÚ
startswithÚappend)Úpkg_librariesÚ	librariesÚlibrary_dirsÚinclude_dirsÚpkgÚtoken© r   ú[/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/libutils.pyÚ
pkg_config%   s"    




r   c             C   s2   t | ƒ\}}}g }x|D ]}| d| ¡ qW |S )zI Returns a list of header strings that could be passed to a compiler
    z-I)r   r   )r   Ú_Zheader_dirsZheader_stringsZ
header_dirr   r   r   Úpkg_config_header_stringsI   s
    
r   c             C   s   t  d | ¡¡dkS )Nz#pkg-config --exists {0} 2>/dev/nullr   )r   r	   r   )Úpackager   r   r   Úpkg_config_check_existsU   s    r   c          	   C   sÎ   t j dd¡rg S tt jdƒ@}ytjddg|d W n"   tdtj	d d	t jd< g S W dQ R X x"| D ]}t
|ƒsjtd
 |¡ƒ‚qjW g }x<td d | ¡¡ƒ ¡ D ] }| d¡r¦| |dd… ¡ q¦W |S )a  
    Returns a list of all library paths that pkg-config says should be included when
    linking against the list of packages given as 'packages'. An empty return list means
    that the package may be found in the standard system locations, irrespective of
    pkg-config.
    ZNO_PKGCONFIGNÚwz
pkg-configz	--version)Ústdoutz>PyCBC.libutils: pkg-config call failed, setting NO_PKGCONFIG=1)ÚfileÚ1z9Package {0} cannot be found on the pkg-config search pathz;PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs-only-L {0}r   z-Lr   )r   ÚenvironÚgetÚopenÚdevnullÚ
subprocessÚ
check_callr
   r   Ústderrr   Ú
ValueErrorr   r   r   r   r   r   )ÚpackagesZFNULLr   Úlibdirsr   r   r   r   Úpkg_config_libdirsX   s&    	



r.   c             C   sè   t |ƒ}xÚt|ƒdkrâ| ¡ }g }y‚x|t |¡D ]n}t |d|  d ¡s”t |d|  d ¡s”t |d|  d ¡s”t || d ¡s”t |d|  d ¡r0| |¡ q0W W n tk
r¸   Y nX t|ƒdkr
| ¡  tj	 
||d	 ¡S q
W d
S )aÜ  
    This function tries to find the architecture-independent library given by libname in the first
    available directory in the list dirs. 'Architecture-independent' means omitting any prefix such
    as 'lib' or suffix such as 'so' or 'dylib' or version number.  Within the first directory in which
    a matching pattern can be found, the lexicographically first such file is returned, as a string
    giving the full path name.  The only supported OSes at the moment are posix and mac, and this
    function does not attempt to determine which is being run.  So if for some reason your directory
    has both '.so' and '.dylib' libraries, who knows what will happen.  If the library cannot be found,
    None is returned.
    r   Úlibz.so*z.dylib*z	.*.dylib*z.dllZcygz-*.dlléÿÿÿÿN)r   r   Úpopleftr   ÚlistdirÚfnmatchr   ÚOSErrorÚsortÚpathr   )ÚlibnameÚdirsZdirqueueZnextdirÚpossibleZlibfiler   r   r   Úget_libpath_from_dirlist|   s$    r:   c             C   s¨   g }dt jkr"|t jd  d¡7 }y|t|ƒ7 }W n tk
rF   Y nX | t j tj	d¡¡ t
| |ƒ}|dkrxt| ƒ}|dkr„dS |dkr–t |¡S tj||dS dS )aÙ  
    This function takes a library name, specified in architecture-independent fashion (i.e.
    omitting any prefix such as 'lib' or suffix such as 'so' or 'dylib' or version number) and
    a list of packages that may provide that library, and according first to LD_LIBRARY_PATH,
    then the results of pkg-config, and falling back to the system search path, will try to
    return a CDLL ctypes object.  If 'mode' is given it will be used when loading the library.
    ZLD_LIBRARY_PATHú:r/   N)Úmode)r   r$   r   r.   r+   r   r6   r   r   Úprefixr:   r   ÚctypesÚCDLL)r7   r,   r<   r-   Úfullpathr   r   r   Úget_ctypes_library   s     


rA   c             C   s8   y
t  | ¡S  tk
r2   G dd„ dtƒ}|| ƒS X dS )aj   Try to import library but and return stub if not found

    Parameters
    ----------
    library_name: str
        The name of the python library to import

    Returns
    -------
    library: library or stub
        Either returns the library if importing is sucessful or it returns
        a stub which raises an import error and message when accessed.
    c                   s$   e Zd Zdd„ Z‡ fdd„Z‡  ZS )z"import_optional.<locals>.no_modulec             S   s
   || _ d S )N)Úlibrary)ÚselfrB   r   r   r   Ú__init__Ù   s    z+import_optional.<locals>.no_module.__init__c                s^   |dkrt ƒ  |¡S | j}t ¡ }t |d¡}|d d }d |||||¡}tt |¡ƒ‚d S )NrB   r   r   é   a9   The function {} tried to access
                         '{}' of library '{}', however,
                        '{}' is not currently installed. To enable this
                        functionality install '{}' (e.g. through pip
                        / conda / system packages / source).
                      )	ÚsuperÚ__getattribute__rB   ÚinspectÚcurrentframeÚgetouterframesr   ÚImportErrorÚcleandoc)rC   Úattrr/   ZcurframeZcalframeZfunÚmsg)Ú	__class__r   r   rG   Ü   s    z3import_optional.<locals>.no_module.__getattribute__)Ú__name__Ú
__module__Ú__qualname__rD   rG   Ú__classcell__r   r   )rO   r   Ú	no_moduleØ   s   rT   N)Ú	importlibÚimport_modulerK   Úobject)Zlibrary_namerT   r   r   r   Úimport_optionalÅ   s
    
rX   )Ú__doc__rU   rH   r   r3   r>   r   r(   Úctypes.utilr   Úcollectionsr   r   ZDEFAULT_MODEZDEFAULT_RTLD_MODEr   r   r   r.   r:   rA   rX   r   r   r   r   Ú<module>   s   ($$!(