U
    eezC                     @   s   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mZm	Z	m
Z
 d dlmZmZmZ d dlZd dlZd dlZd dlmZmZmZmZ d dlmZmZmZmZmZmZ d dlmZ dd	d
ZdddgZ dd Z!G dd dZ"dd Z#dS )    N)joindirnameisdirnormpathsplitextbasename)listdirwalksep)shprintinfologgerdebug)current_directory
ensure_dirtemp_directoryBuildInterruptingExceptionrmdirmove)RecipeTFc                 C   s   t | D ]\}}}|D ]}t|| d}|tr@|dd  }t||}	tj|	s`t	|	 t||}
t|	|}tj
|
r|rtj|rt| tj|s|rt|
| qt|
| qt	| qqd S )N    )r	   r   replace
startswithr
   r   ospathexistsmakedirsisfileunlinksymlinkshutilcopy)Zsrc_rootZ	dest_rootoverrider    rootdirnames	filenamesfilenamesubdirdest_dirZsrc_file	dest_file r+   >/tmp/pip-unpacked-wheel-h4dze4ss/pythonforandroid/bootstrap.py
copy_files   s$    





r-   webviewsdl2Zservice_onlyc                 C   s@   dd }|| }||}||kr(|| S | j |j k r8dS dS d S )Nc                 S   s   | j tkrt| j d S dS )zi Returns a ranking index for each bootstrap,
            with higher priority ranked with higher number. r   r   )namedefault_recipe_prioritiesindex)	bootstrapr+   r+   r,   rank_bootstrap3   s    
z3_cmp_bootstraps_by_priority.<locals>.rank_bootstrapr   r0   )abr4   Zrank_aZrank_br+   r+   r,   _cmp_bootstraps_by_priority2   s    r9   c                   @   s  e Zd ZdZdZdZdZdZdZdZ	ddgZ
dZedd Zed	d
 Zdd Zdd Zdd Zdd Zedd Zdd Zdd Zdd Zdd Zdd Zedd  Zed!d" Zed#d$ Zed%d& Zd6d)d*Zd7d,d-Zd.d/ Z d0d1 Z!d2d3 Z"d4d5 Z#dS )8	BootstrapzpAn Android project template, containing recipe stuff for
    compilation and templated fields for APK info.
    z/jniNpython3ZandroidTc                 C   s"   | j dkrtd| | | j jS )z9The dist dir at which to place the finished distribution.NzHInternal error: tried to access {}.dist_dir, but {}.distribution is None)distributionr   formatdist_dirselfr+   r+   r,   r>   a   s    
 zBootstrap.dist_dirc                 C   s   | j | j S N)r0   
jni_subdirr?   r+   r+   r,   jni_dirj   s    zBootstrap.jni_dirc                 C   sR   g }| j jpg }| jD ]2}t|ttfr|D ]}||kr,||  qq,qt|S )zChecks what recipes are being built to see which of the alternative
        and optional dependencies are being used,
        and returns a list of these.)ctxZrecipe_build_orderrecipe_depends
isinstancetuplelistappendsorted)r@   recipesZbuilt_recipesrecipealternativer+   r+   r,   check_recipe_choicesn   s    

zBootstrap.check_recipe_choicesc                 C   s   |   }d| jg| }|S )N-)rN   r   r0   )r@   choicesZdir_namer+   r+   r,   get_build_dir_name|   s    zBootstrap.get_build_dir_namec                 C   s   t | jjd|  S )NZbootstrap_builds)r   rD   	build_dirrQ   r?   r+   r+   r,   get_build_dir   s    zBootstrap.get_build_dirc                 C   s   t | jj|S rA   )r   rD   r>   )r@   r0   r+   r+   r,   get_dist_dir   s    zBootstrap.get_dist_dirc                 C   s   | j j}|ddd S )N.   r5   )	__class__
__module__split)r@   modnamer+   r+   r,   r0      s    zBootstrap.namec                    s>    j jdd }dd |D dg } fddt|D }|S )z5get all bootstrap directories, following the MRO pathNc                 S   s   g | ]
}|j qS r+   r6   ).0clsr+   r+   r,   
<listcomp>   s     z0Bootstrap.get_bootstrap_dirs.<locals>.<listcomp>commonc                    s   g | ]}t  jjd |qS )
bootstraps)r   rD   root_dir)r\   Zbootstrap_namer?   r+   r,   r^      s   )rW   __mro__reversed)r@   classesZbootstrap_namesbootstrap_dirsr+   r?   r,   get_bootstrap_dirs   s    
zBootstrap.get_bootstrap_dirsc                 C   s   | j dkrtd| j}| }t|dddddddd	d
}t| jddddd	d}td
t|  t	j
|svt	| t||dd d S )Nr/   ZSDLzandroid-projectZappsrcmainjavaorgZlibsdlz"Copying in SDL2 .java files from: T)r#   )r0   r   
get_reciperD   Zget_jni_dirr   r>   r   strr   r   r   r   r-   )r@   Zsdl2_recipeZsdl2_build_dirsrc_dir
target_dirr+   r+   r,   _copy_in_final_files   s(    
      
zBootstrap._copy_in_final_filesc              
   C   sz   |   }|  | _|D ]}tt|d| j| jjd qt| j0 tdd}|	d
| jj W 5 Q R X W 5 Q R X dS )zzEnsure that a build dir exists for the recipe. This same single
        dir will be used for building all different archs.build)r    zproject.propertieswztarget=android-{}N)rf   rS   rR   r-   r   rD   Zsymlink_bootstrap_filesr   openwriter=   Zandroid_api)r@   re   bootstrap_dirZfilehr+   r+   r,   prepare_build_dir   s    
zBootstrap.prepare_build_dirc                 C   s   t | j d S rA   )r   r>   r?   r+   r+   r,   prepare_dist_dir   s    zBootstrap.prepare_dist_dirc                 C   s   |    | j| j dS )z Copies all the files into the distribution (this function is
            overridden by the specific bootstrap classes to do this)
            and add in the distribution info.
        N)ro   r<   Z	save_infor>   r?   r+   r+   r,   assemble_distribution   s    zBootstrap.assemble_distributionc                 C   sP   d}t ttd}t }t|D ]*}||kr.q t ||}t|r || q |S )z2Find all the available bootstraps and return them.)__pycache__r_   r`   )r   r   __file__setr   r   add)r]   Zforbidden_dirsZbootstraps_dirresultr0   filenr+   r+   r,   all_bootstraps   s    
zBootstrap.all_bootstrapsc           
         s  t d  fdd  D }t }|D ]}|js6q*t|j}|D ]d}D ]0}t|}tfdd|j	D rRd} qqRD ]R}zt|}W n t
k
r   g }	Y nX |j	}	tfdd|	D rd} qq|rF||krF|| qFq*t d	t|d
d |D  |S )zwReturns all bootstrap whose recipe requirements do not conflict
        with the given recipes, in no particular order.z:Trying to find a bootstrap that matches the given recipes.c                    s   g | ]}  |qS r+   )get_bootstrap)r\   r0   )r]   rD   r+   r,   r^      s   z?Bootstrap.get_usable_bootstraps_for_recipes.<locals>.<listcomp>Tc                 3   s   | ]}| kV  qd S rA   r+   r\   conflict)rK   r+   r,   	<genexpr>   s     z>Bootstrap.get_usable_bootstraps_for_recipes.<locals>.<genexpr>Fc                 3   s   | ]}| kV  qd S rA   r+   r   )possible_dependenciesr+   r,   r      s   z"Found {} acceptable bootstraps: {}c                 S   s   g | ]
}|j qS r+   r6   )r\   bsr+   r+   r,   r^      s     )r   r~   rz   can_be_chosen_automaticallyexpand_dependenciesrE   r   rk   any	conflicts
ValueErrorr{   r=   len)
r]   rK   rD   r`   acceptable_bootstrapsr   Zpossible_dependency_listsokrL   r   r+   )r]   rD   r   rK   r,   !get_usable_bootstraps_for_recipes   sD    
z+Bootstrap.get_usable_bootstraps_for_recipesc                    s   dh}t || | ||} fdd}|drVddd |D krVtd | d|S |D ]B}||rZdd	d |D krZtd
|| | d|  S qZtt|t	t
d}|rtd|d j |d S dS )zPicks a single recommended default bootstrap out of
           all_usable_bootstraps_from_recipes() for the given reicpes,
           and returns it.Zflaskc                    s    D ]}| |kr dS qdS )NTFr+   )depZdep_listZrecipes_with_deps_listsr+   r,   have_dependency_in_recipes  s    zHBootstrap.get_bootstrap_from_recipes.<locals>.have_dependency_in_recipesr/   c                 S   s   g | ]
}|j qS r+   r6   r\   r8   r+   r+   r,   r^     s     z8Bootstrap.get_bootstrap_from_recipes.<locals>.<listcomp>z0Using sdl2 bootstrap since it is in dependenciesr.   c                 S   s   g | ]
}|j qS r+   r6   r   r+   r+   r,   r^     s     z?Using webview bootstrap since common web packages were found {})keyz+Using the highest ranked/first of these: {}r   N)r   r   r   r   r=   intersectionrJ   rH   	functools
cmp_to_keyr9   r0   )r]   rK   rD   Zknown_web_packagesr   r   Zpossible_web_depZ!prioritized_acceptable_bootstrapsr+   r   r,   get_bootstrap_from_recipes   s:    
 z$Bootstrap.get_bootstrap_from_recipesc                 C   s~   |dkrdS t | dsi | _|| jkr0| j| S td|}ttjdkr^ttjd  |j	}t
|jd||_||_|S )zReturns an instance of a bootstrap with the given name.

        This is the only way you should access a bootstrap class, as
        it sets the bootstrap directory correctly.
        Nr`   zpythonforandroid.bootstraps.{}r   )hasattrr`   	importlibimport_moduler=   r   r   handlersremoveHandlerr3   r   ra   rt   rD   )r]   r0   rD   modr3   r+   r+   r,   r   )  s    


zBootstrap.get_bootstrap*libsc                 C   sT   t d t||j}t| |D ].}tt||}|r ttjdf||f  q dS )z<Copy existing arch libs from build dirs to current dist dir.zCopying libs-aN)r   r   archr   globr   shcp)r@   r   Zsrc_dirsZwildcardr)   Ztgt_dirrm   r   r+   r+   r,   distribute_libs?  s    zBootstrap.distribute_libsrg   c                 C   s4   t d t| t|}ttjdf||f  dS )z=Copy existing javaclasses from build dir to current dist dir.zCopying java filesr   N)r   r   r   r   r   r   )r@   Zjavaclass_dirr)   r&   r+   r+   r,   distribute_javaclassesI  s    
z Bootstrap.distribute_javaclassesc                 C   s2   t d tt| jjdD ]}| || qdS )z;Process existing .aar bundles and copy to current dist dir.zUnpacking aarsz*.aarN)r   r   r   rD   Zaars_dir_unpack_aar)r@   r   aarr+   r+   r,   distribute_aarsP  s    zBootstrap.distribute_aarsc              	   C   s4  t  "}tt|d }|d }td| td| td| ttjd|d| t	|d}t	d	|}td
| td| td| t
d	 ttjd|| t	|d|j}t	d	|j}	td| td| td|	 t
|	 tt	|d}
ttjdf|
|	f  W 5 Q R X dS )z;Unpack content of .aar bundle and copy to current dist dir.r   z.jarzunpack {} aarz	  from {}z  to {}z-oz-dzclasses.jarr   zcopy {} jarr   Zjnizcopy {} .so*.soN)r   r   r   r   r=   r   r   r   Zunzipr   r   r   r   r   )r@   r   r   temp_dirr0   Zjar_nameZjar_srcZjar_tgtZ
so_src_dirZ
so_tgt_dirZso_filesr+   r+   r,   r   V  s,    


zBootstrap._unpack_aarc              	   C   s   t d | }t|d }t|d }t|dkrJ||dd  }t| j	d|j
 dd}ttj|t| j	dd	d
|djd}t d |dD ]@}|sqz|||d W q tjk
r   td|  Y qX qd S )NzStripping librariesZSTRIPr   r   Z_python_bundle__Z_python_bundlemodulesr   z-inamer   )Z_envzutf-8z"Stripping libraries in private dir
zFailed to strip )r   Zget_envshlexrY   r   Commandr   Zbaker   r>   r   r   findstdoutdecoder   ZErrorReturnCode_1r   )r@   r   envtokensstripZlibs_dirZfilensr}   r+   r+   r,   strip_librariesq  s2       
zBootstrap.strip_librariesc                    sz   t d| t|D ]^}t|| t r|drt d|   fddt D }|D ]}t|| q\t| qd S )NzFrying eggs in {}z.eggz  c                    s   g | ]}|d krt  |qS )zEGG-INFO)r   )r\   frdr+   r,   r^     s      z&Bootstrap.fry_eggs.<locals>.<listcomp>)r   r=   r   r   r   endswithr   r   )r@   sitepackagesdfilesr   r+   r   r,   fry_eggs  s    
zBootstrap.fry_eggs)r   r   )rg   )$__name__rX   __qualname____doc__rB   rD   rt   rR   	dist_namer<   rE   r   propertyr>   rC   rN   rQ   rS   rT   r0   rf   ro   ru   rv   rw   classmethodr~   r   r   r   r   r   r   r   r   r   r+   r+   r+   r,   r:   F   sL   




*
.



r:   c              	   C   s   t | }| D ]d}t|tt fr*t|dkrt|tt fr@|d }zt||}||j7 }W q tk
rn   Y qX qg g}|D ]f}t|tt frg }|D ]0}|D ]&}dd |D }	|	| ||	 qq|}q||D ]}
|
| qq||S )aX   This function expands to lists of all different available
        alternative recipe combinations, with the dependencies added in
        ONLY for all the not-with-alternative recipes.
        (So this is like the deps graph very simplified and incomplete, but
         hopefully good enough for most basic bootstrap compatibility checks)
    r   r   c                 S   s   g | ]}|qS r+   r+   )r\   ir+   r+   r,   r^     s     z'expand_dependencies.<locals>.<listcomp>)	rH   rF   rG   r   r   rk   dependsr   rI   )rK   rD   Zrecipes_with_depsentryrL   Zrecipe_listsZnew_recipe_listsrM   Zold_listZnew_listZexisting_listr+   r+   r,   r     s.    	
r   )TF)$r   r   r   r   os.pathr   r   r   r   r   r   r   r	   r
   r   r   r!   Zpythonforandroid.loggerr   r   r   r   Zpythonforandroid.utilr   r   r   r   r   r   Zpythonforandroid.reciper   r-   r1   r9   r:   r   r+   r+   r+   r,   <module>   s*     
  	  O