a
    ”$a>š  ã                	   @   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mZmZm	Z	 dZ
dZdZdZdZdZd	Zd
ZdZdZdZdZdZdZi ZG dd„ deƒZedefi ƒZG dd„ deƒZejdkrÌdd„ Zejj e_ ee_dd„ Z dd„ Z!G dd„ deƒZ"dd „ Z#d!d"„ Z$e %d#¡Z&e %d$¡Z'e %d%ej(¡Z)d&d'„ Z*e %d(ej(¡Z+d)d*„ Z,d7d,d-„Z-d.d/„ Z.ddd0g g g g d+df	d1d2„Z/d3d4„ Z0eZ1G d5d6„ d6eƒZ2dS )8z6
Tasks represent atomic operations such as processes.
é    N)ÚUtilsÚLogsÚErrorsé   é   é   é   é   é	   éÿÿÿÿéþÿÿÿéýÿÿÿéüÿÿÿa  
def f(tsk):
	env = tsk.env
	gen = tsk.generator
	bld = gen.bld
	cwdx = tsk.get_cwd()
	p = env.get_flat
	def to_list(xx):
		if isinstance(xx, str): return [xx]
		return xx
	tsk.last_cmd = cmd = ''' %s ''' % s
	return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None)
a  
def f(tsk):
	env = tsk.env
	gen = tsk.generator
	bld = gen.bld
	cwdx = tsk.get_cwd()
	def to_list(xx):
		if isinstance(xx, str): return [xx]
		return xx
	def merge(lst1, lst2):
		if lst1 and lst2:
			return lst1[:-1] + [lst1[-1] + lst2[0]] + lst2[1:]
		return lst1 + lst2
	lst = []
	%s
	if '' in lst:
		lst = [x for x in lst if x]
	tsk.last_cmd = lst
	return tsk.exec_command(lst, cwd=cwdx, env=env.env or None)
zå
def f(tsk):
	sig = tsk.generator.bld.hash_env_vars(tsk.env, tsk.vars)
	tsk.m.update(sig)
	env = tsk.env
	gen = tsk.generator
	bld = gen.bld
	cwdx = tsk.get_cwd()
	p = env.get_flat
	buf = []
	%s
	tsk.m.update(repr(buf).encode())
c                       s    e Zd ZdZ‡ fdd„Z‡  ZS )Ústore_task_typezä
	Metaclass: store the task classes into the dict pointed by the
	class attribute 'register' which defaults to :py:const:`waflib.Task.classes`,

	The attribute 'run_str' is compiled into a method 'run' bound to the task class.
	c                    sÜ   t t| ƒ |||¡ | j}|dkrØ|dkrØt| dd ƒr¤t| j| jƒ\}}t 	| j¡| _
| j| _d | _|| _tt| j| ƒƒ| _| j ¡  | jrÈt| jƒ}|rÈ|| _n$t| dd ƒrÈd| jvrÈt 	| j¡| _
| t| dtƒ|< d S )NÚevilÚTaskÚrun_strÚrunÚhcodeÚregister)Úsuperr   Ú__init__Ú__name__ÚgetattrÚcompile_funr   Úshellr   Zh_cmdr   Zorig_run_strr   ÚlistÚsetÚvarsÚsortÚcompile_sig_varsÚsig_varsÚ__dict__Úclasses)ÚclsÚnameÚbasesÚdictÚfÚdvarsÚfun©Ú	__class__© úf/home/jack/SDK/ZBT-AX3000-OpenWrt-21.02/build_dir/hostpkg/samba-4.14.12/third_party/waf/waflib/Task.pyr   l   s$    

zstore_task_type.__init__)r   Ú
__module__Ú__qualname__Ú__doc__r   Ú__classcell__r-   r-   r+   r.   r   e   s   r   r   c                   @   sN  e Zd ZdZg ZdZdZdZg Zg Z	g Z
g ZejZdZdZdZdZdZdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z d d!„ Z!d"d#„ Z"d$d%„ Z#d&d'„ Z$d(d)„ Z%d*d+„ Z&d,d-„ Z'd.d/„ Z(d0d1„ Z)d2d3„ Z*d4d5„ Z+d6d7„ Z,d8d9„ Z-d:d;„ Z.d<d=„ Z/d>d?„ Z0d@Z1dAdB„ Z2dCdD„ Z3dEdF„ Z4d@S )Gr   a{  
	Task objects represents actions to perform such as commands to execute by calling the `run` method.

	Detecting when to execute a task occurs in the method :py:meth:`waflib.Task.Task.runnable_status`.

	Detecting which tasks to execute is performed through a hash value returned by
	:py:meth:`waflib.Task.Task.signature`. The task signature is persistent from build to build.
	FÚGREENr   )ÚhasrunÚ	generatorÚenvÚinputsÚoutputsÚ	dep_nodesÚ	run_afterc                 O   sV   t | _z|d | _W n ty,   | | _Y n0 |d | _g | _g | _g | _tƒ | _	d S )Nr5   r6   )
ÚNOT_RUNr4   r5   ÚKeyErrorr6   r7   r8   r9   r   r:   )ÚselfÚkÚkwr-   r-   r.   r   Â   s    
zTask.__init__c                 C   s   |   ¡ |  ¡ kS ©N©Úpriority©r=   Úotherr-   r-   r.   Ú__lt__Ø   s    zTask.__lt__c                 C   s   |   ¡ |  ¡ kS r@   rA   rC   r-   r-   r.   Ú__le__Ú   s    zTask.__le__c                 C   s   |   ¡ |  ¡ k S r@   rA   rC   r-   r-   r.   Ú__gt__Ü   s    zTask.__gt__c                 C   s   |   ¡ |  ¡ kS r@   rA   rC   r-   r-   r.   Ú__ge__Þ   s    zTask.__ge__c                 C   sX   | j j}t| ddƒp t|d|jƒ}t|tƒrTtj |¡rF|j	 
|¡}n| j j 
|¡}|S )zO
		:return: current working directory
		:rtype: :py:class:`waflib.Node.Node`
		ÚcwdN)r5   Úbldr   ÚbldnodeÚ
isinstanceÚstrÚosÚpathÚisabsÚrootÚ	make_node)r=   rJ   Úretr-   r-   r.   Úget_cwdá   s    
zTask.get_cwdc                 C   sX   |}d|v r|  dd¡}d|v r,|  dd¡}||ksLd|v sLd|v sLd|v rTd| }|S )	z¬
		Surround a process argument by quotes so that a list of arguments can be written to a file

		:param x: flag
		:type x: string
		:return: quoted flag
		:rtype: string
		ú\ú\\ú"z\"ú ú	ú'z"%s")Úreplace)r=   ÚxÚoldr-   r-   r.   Ú
quote_flagï   s    	 zTask.quote_flagc                 C   s   | j | j t| jddƒ fS )zw
		Priority of execution; the higher, the earlier

		:return: the priority value
		:rtype: a tuple of numeric values
		Ztg_idx_countr   )ÚweightÚ
prio_orderr   r5   ©r=   r-   r-   r.   rB     s    zTask.priorityc                    s$   |d g‡ fdd„|dd… D ƒfS )z½
		Splits a list of process commands into the executable part and its list of arguments

		:return: a tuple containing the executable first and then the rest of arguments
		:rtype: tuple
		r   c                    s   g | ]}ˆ   |¡‘qS r-   )r^   ©Ú.0r\   ra   r-   r.   Ú
<listcomp>  ó    z&Task.split_argfile.<locals>.<listcomp>r   Nr-   )r=   Úcmdr-   ra   r.   Úsplit_argfile
  s    zTask.split_argfilec                 K   sò  d|vr|   ¡ |d< t| dƒr(| j|d< | jjr~t| d¡pH| jjpHtjƒ }|d< t	| jjt
ƒrj| jjntj | jj¡|d< t| dƒr’| j|d< t| dƒr¦| j|d< t	|t
ƒsÜtjrØtdd„ |D ƒƒt|ƒ d	k}nt|ƒd
k}|rÜt| ddƒrÜ|  |¡\}}z®t ¡ \}}t |d |¡ ¡ ¡ t |¡ tjrJt d||¡ | jjj|d| g fi |¤ŽW zt  |¡ W S  t!yŒ   Y S 0 S zt  |¡ W n t!y²   Y n0 n&zt  |¡ W n t!yØ   Y n0 0 | jjj|fi |¤ŽS )a¶  
		Wrapper for :py:meth:`waflib.Context.Context.exec_command`.
		This version set the current working directory (``build.variant_dir``),
		applies PATH settings (if self.env.PATH is provided), and can run long
		commands through a temporary ``@argfile``.

		:param cmd: process command to execute
		:type cmd: list of string (best) or string (process will use a shell)
		:return: the return code
		:rtype: int

		Optional parameters:

		#. cwd: current working directory (Node or string)
		#. stdout: set to None to prevent waf from capturing the process standard output
		#. stderr: set to None to prevent waf from capturing the process standard error
		#. timeout: timeout value (Python 3)
		rI   Útimeoutr6   ÚPATHÚstdoutÚstderrc                 S   s   g | ]}t |ƒ‘qS r-   )Úlen)rc   Úargr-   r-   r.   rd   8  re   z%Task.exec_command.<locals>.<listcomp>i    i@ Zallow_argsfileTz
zargfile: @%r -> %rú@)"rT   Úhasattrrh   r6   ri   r'   ÚgetrN   ÚenvironrL   rM   ÚpathsepÚjoinrj   rk   r   Zis_win32Úsumrl   r   rg   ÚtempfileZmkstempÚwriteÚencodeÚcloser   ÚverboseÚdebugr5   rJ   Úexec_commandÚremoveÚOSError)r=   rf   r?   r6   Ztoo_longÚargsÚfdÚtmpr-   r-   r.   r{     sL    

$*



 
 úüzTask.exec_commandc                 C   sî   z| j jj|  ¡ = W n ty&   Y n0 z|  ¡ }W n" tyV   t ¡ | _	t
| _Y n\0 |rj|| _t| _nHz|  ¡  W n4 tjyŠ   Y n( tyª   t ¡ | _	t
| _Y n0 t| _| jtkrê| jrêz| j jj|  ¡ = W n tyè   Y n0 dS )zd
		Runs the task and handles errors

		:return: 0 or None if everything is fine
		:rtype: integer
		N)r5   rJ   Ú	task_sigsÚuidr<   r   Ú	ExceptionÚ	tracebackZ
format_excÚerr_msgÚ	EXCEPTIONr4   Úerr_codeÚCRASHEDÚpost_runr   ÚWafErrorÚSUCCESSÚscanÚimp_sigs©r=   rS   r-   r-   r.   ÚprocessO  s2    	

zTask.processc                 C   s„   | j jjdkrdS |  ¡ }|r€|jr,|j}nt}| j jjdkrjtjj}tjj}|j	|t
jd||dœd n|j	|ddddœd dS )z1Writes the execution status on the context loggerr   Nr   Ú )ÚstreamÚ
terminatorÚc1Úc2)Úextra)r’   r“   r”   )r5   rJ   Úprogress_barÚdisplayÚloggerr   ÚcolorsZ
cursor_offZ	cursor_onÚinfoÚsysrk   )r=   rJ   Úsr˜   r“   r”   r-   r-   r.   Úlog_displayx  s    zTask.log_displayc                    s@  t  | j¡}t jj}| jjj‰ ‡ fdd„}| jjjdkrP| jj |ƒ ˆ j	||¡S | jjjdkræt
| jjjƒ}zd dd„ | jD ƒ¡}W n tyœ   d}Y n0 zd d	d„ | jD ƒ¡}W n tyÎ   d}Y n0 d
ˆ j	|ƒ |||f S t
| ƒ}|södS ˆ j	}tt
|ƒƒ}	d|	|	f }
|  ¡ }|r*|d7 }|
|ƒ |||||f S )zi
		Returns an execution status for the console, the progress bar, or the IDE output.

		:rtype: string
		c                      s   ˆ j ˆ j ¡  S r@   )Ú	processedZreadyZqsizer-   ©Zmasterr-   r.   Úcur•  s    zTask.display.<locals>.curr   r   ú,c                 S   s   g | ]
}|j ‘qS r-   ©r%   ©rc   Únr-   r-   r.   rd   Ÿ  re   z Task.display.<locals>.<listcomp>r   c                 S   s   g | ]
}|j ‘qS r-   r¢   r£   r-   r-   r.   rd   £  re   z3|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|
Nz[%%%dd/%%%dd] %%s%%s%%s%%s
rX   )r   r™   ÚcolorZNORMALr5   rJ   Zproducerr–   Zprogress_lineÚtotalrM   Ztimerrs   r7   ÚAttributeErrorr8   rl   Úkeyword)r=   Zcol1Zcol2r    ZelaÚinsÚoutsrœ   r¦   r¤   Zfsr?   r-   rŸ   r.   r—   ‹  s6    


zTask.displayc                 C   s.   t | jƒt | jƒt | jƒt | jƒ| jj| jfS )z–
		Identifies a task type for all the constraints relevant for the scheduler: precedence, file production

		:return: a hash value
		:rtype: string
		)ÚtupleÚbeforeÚafterÚext_inÚext_outr,   r   r   ra   r-   r-   r.   Úhash_constraints´  s    zTask.hash_constraintsc                 C   sÊ   t jrd| t| ddƒf }nd}t| jddƒ}t| ddƒr@| jS | jsRd|| f S | jtkrzd	|| j|f W S  tyŒ   d
||f  Y S 0 n6| jt	kr¦d||f S | jt
kr¸d| S d|| jf S dS )zU
		Returns an error message to display the build failure reasons

		:rtype: string
		z: %r
%rÚlast_cmdr   z* (run with -v to display more information)r%   r…   Nz/task in %r was not executed for some reason: %rz+ -> task in %r failed with exit status %r%sz -> task in %r failed%sz -> missing files in %r%sz/ -> %r canceled because of missing dependenciesz!invalid status for task in %r: %r)r   ry   r   r5   r…   r4   rˆ   r‡   r§   ÚMISSINGÚCANCELED)r=   Úmsgr%   r-   r-   r.   Úformat_error½  s$    


zTask.format_errorc                    sr   | j | ‰ ˆ sg S t|tƒr(| j | }n|}tˆ tƒrH‡ fdd„|D ƒS g }|D ]}| ˆ ¡ | |¡ qP|S dS )a˜  
		Enable scriptlet expressions of the form ${FOO_ST:FOO}
		If the first variable (FOO_ST) is empty, then an empty list is returned

		The results will be slightly different if FOO_ST is a list, for example::

			env.FOO    = ['p1', 'p2']
			env.FOO_ST = '-I%s'
			# ${FOO_ST:FOO} returns
			['-Ip1', '-Ip2']

			env.FOO_ST = ['-a', '-b']
			# ${FOO_ST:FOO} returns
			['-a', '-b', 'p1', '-a', '-b', 'p2']
		c                    s   g | ]}ˆ | ‘qS r-   r-   rb   ©r€   r-   r.   rd   ñ  re   zTask.colon.<locals>.<listcomp>N)r6   rL   rM   ÚextendÚappend)r=   Zvar1Zvar2ÚitÚlstÚyr-   r¶   r.   ÚcolonØ  s    



z
Task.colonc                 C   sÄ   | j j}| jr8| d¡s| js8| jd }| |j ¡ ¡S | jsL| jsL| j jS t| jƒdkrt| jd }| |j ¡ ¡S d 	dd„ | jD ƒ¡}d 	dd„ | jD ƒ¡}| jr¬d}nd	}d
| j j|||f S )zstring to display to the user©ÚlibÚprogramr   r   rX   c                 S   s   g | ]}|  |j ¡ ¡‘qS r-   ©Ú	path_fromÚctxÚlaunch_node©rc   Úar-   r-   r.   rd     re   z Task.__str__.<locals>.<listcomp>c                 S   s   g | ]}|  |j ¡ ¡‘qS r-   rÀ   rÄ   r-   r-   r.   rd     re   ú -> r   z
%s: %s%s%s)
r,   r   r8   Úendswithr7   rÁ   rÂ   rÃ   rl   rs   )r=   r%   ÚnodeZsrc_strZtgt_strÚsepr-   r-   r.   Ú__str__ù  s     

zTask.__str__c                 C   sN   | j j}| d¡rdS t| jƒdkr6t| jƒdkr6dS | jsJ| jrFdS dS dS )z4Display keyword used to prettify the console outputsr½   ZLinkingr   Z	CompilingZCreatingZRunningZ
Processing)r,   r   rÇ   rl   r7   r8   )r=   r%   r-   r-   r.   r¨     s    
zTask.keywordc              	   C   s”   z0d  dd„ | jD ƒ¡}d  dd„ | jD ƒ¡}W n> tyn   d  dd„ | jD ƒ¡}d  dd„ | jD ƒ¡}Y n0 d  dt| ƒ | jjd	|d
|dg¡S )zfor debugging purposesr¡   c                 S   s   g | ]
}|j ‘qS r-   r¢   rb   r-   r-   r.   rd     re   z!Task.__repr__.<locals>.<listcomp>c                 S   s   g | ]
}|j ‘qS r-   r¢   rb   r-   r-   r.   rd      re   c                 S   s   g | ]}t |ƒ‘qS r-   ©rM   rb   r-   r-   r.   rd   "  re   c                 S   s   g | ]}t |ƒ‘qS r-   rË   rb   r-   r-   r.   rd   #  re   r   z
	{task %r: rX   rÆ   ú})rs   r7   r8   r§   Úidr,   r   )r=   r©   rª   r-   r-   r.   Ú__repr__  s    zTask.__repr__c                 C   sb   z| j W S  ty\   t | jj¡}|j}| j| j D ]}|| 	¡ ƒ q6| 
¡ | _ | j  Y S 0 dS )a  
		Returns an identifier used to determine if tasks are up-to-date. Since the
		identifier will be stored between executions, it must be:

			- unique for a task: no two tasks return the same value (for a given build context)
			- the same for a given task instance

		By default, the node paths, the class name, and the function are used
		as inputs to compute a hash.

		The pointer to the object (python built-in 'id') will change between build executions,
		and must be avoided in such hashes.

		:return: hash value
		:rtype: string
		N)Úuid_r§   r   Úmd5r,   r   Úupdater7   r8   ÚabspathÚdigest©r=   ÚmZupr\   r-   r-   r.   r‚   &  s    
zTask.uidc                 C   s*   t |tƒr|  j|7  _n| j |¡ dS )zj
		Appends the nodes to the *inputs* list

		:param inp: input nodes
		:type inp: node or list of nodes
		N)rL   r   r7   r¸   )r=   Zinpr-   r-   r.   Ú
set_inputsA  s    
zTask.set_inputsc                 C   s*   t |tƒr|  j|7  _n| j |¡ dS )zl
		Appends the nodes to the *outputs* list

		:param out: output nodes
		:type out: node or list of nodes
		N)rL   r   r8   r¸   )r=   Úoutr-   r-   r.   Úset_outputsM  s    
zTask.set_outputsc                 C   s   t |tƒsJ ‚| j |¡ dS )a  
		Run this task only after the given *task*.

		Calling this method from :py:meth:`waflib.Task.Task.runnable_status` may cause
		build deadlocks; see :py:meth:`waflib.Tools.fc.fc.runnable_status` for details.

		:param task: task
		:type task: :py:class:`waflib.Task.Task`
		N)rL   r   r:   Úadd)r=   Útaskr-   r-   r.   Úset_run_afterY  s    
zTask.set_run_afterc                 C   s~   z| j W S  ty   Y n0 t | j¡| _|  ¡  |  ¡  | jrjz|  	¡  W n t
jyh   |  ¡  Y S 0 | j ¡  }| _ |S )a  
		Task signatures are stored between build executions, they are use to track the changes
		made to the input nodes (not to the outputs!). The signature hashes data from various sources:

		* explicit dependencies: files listed in the inputs (list of node objects) :py:meth:`waflib.Task.Task.sig_explicit_deps`
		* implicit dependencies: list of nodes returned by scanner methods (when present) :py:meth:`waflib.Task.Task.sig_implicit_deps`
		* hashed data: variables/values read from task.vars/task.env :py:meth:`waflib.Task.Task.sig_vars`

		If the signature is expected to give a different result, clear the cache kept in ``self.cache_sig``::

			from waflib import Task
			class cls(Task.Task):
				def signature(self):
					sig = super(Task.Task, self).signature()
					delattr(self, 'cache_sig')
					return super(Task.Task, self).signature()

		:return: the signature value
		:rtype: string or bytes
		)Z	cache_sigr§   r   rÐ   r   rÕ   Úsig_explicit_depsr!   rŒ   Úsig_implicit_depsr   Ú
TaskRescanÚ	signaturerÓ   rŽ   r-   r-   r.   rß   f  s    zTask.signaturec                 C   s6  | j j}|jdk rtS | jD ]$}|js.t  S |jtk rt  S qz|  	¡ }W n t
jyf   t Y S 0 |  ¡ }z|j| }W n" ty    t d| ¡ t Y S 0 ||krºt d| ¡ tS | jD ]b}|j |¡}|sèt d| ¡ t  S ||krt d| ¡ t  S | ¡ sÀt d| ¡ t  S qÀ| jr2tp4tS )zÓ
		Returns the Task status

		:return: a task state in :py:const:`waflib.Task.RUN_ME`,
			:py:const:`waflib.Task.SKIP_ME`, :py:const:`waflib.Task.CANCEL_ME` or :py:const:`waflib.Task.ASK_LATER`.
		:rtype: int
		r   zHtask: task %r must run: it was never run before or the task code changedz2task: task %r must run: the task signature changedz7task: task %r must run: an output node has no signaturezCtask: task %r must run: an output node was produced by another taskz5task: task %r must run: an output node does not exist)r5   rJ   Z
is_installÚSKIP_MEr:   r4   Ú	ASK_LATERÚSKIPPEDÚ	CANCEL_MErß   r   ÚTaskNotReadyr‚   r   r<   r   rz   ÚRUN_MEr8   Ú	node_sigsrp   ÚexistsÚ
always_run)r=   rJ   ÚtZnew_sigÚkeyZprev_sigrÈ   Úsigr-   r-   r.   Úrunnable_status’  sB    








zTask.runnable_statusc                 C   s‚   | j j}| jD ]:}| ¡ s:t| _d| ¡  | _t 	| j¡‚|  
¡ |j|< q|  ¡ |j|  
¡ < | js~z| `W n ty|   Y n0 dS )z’
		Called after successful execution to record that the task has run by
		updating the entry in :py:attr:`waflib.Build.BuildContext.task_sigs`.
		z-> missing file: %rN)r5   rJ   r8   rç   r²   r4   rÒ   r…   r   rŠ   r‚   ræ   rß   r   Úkeep_last_cmdr±   r§   )r=   rJ   rÈ   r-   r-   r.   r‰   Æ  s    
zTask.post_runc              
   C   s¶   | j j}| jj}| j| j D ]}|| ¡ ƒ q|jr²|j}| j| j D ]j}z|| }W n t	yl   Y qFY n0 |D ]<}z| ¡ }W n" t
y¤   t|dƒr |ƒ }Y n0 ||ƒ qrqFdS )z™
		Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.inputs`
		and :py:attr:`waflib.Task.Task.dep_nodes` signatures.
		Ú__call__N)r5   rJ   rÕ   rÑ   r7   r9   Úget_bld_sigZdeps_manr8   r<   r§   ro   )r=   rJ   Úupdr\   Zadditional_depsÚdÚvr-   r-   r.   rÜ   Ù  s$    

zTask.sig_explicit_depsc                    s8   | j j‰ ‡ fdd„| j| j D ƒ}| j t |¡¡ dS )a  
		Enable rebuilds on input files task signatures. Not used by default.

		Example: hashes of output programs can be unchanged after being re-linked,
		despite the libraries being different. This method can thus prevent stale unit test
		results (waf_unit_test.py).

		Hashing input file timestamps is another possibility for the implementation.
		This may cause unnecessary rebuilds when input tasks are frequently executed.
		Here is an implementation example::

			lst = []
			for node in self.inputs + self.dep_nodes:
				st = os.stat(node.abspath())
				lst.append(st.st_mtime)
				lst.append(st.st_size)
			self.m.update(Utils.h_list(lst))

		The downside of the implementation is that it absolutely requires all build directory
		files to be declared within the current build.
		c                    s$   g | ]}|  ¡ rˆ jˆ j|  ‘qS r-   )Úis_bldr   ræ   )rc   rÈ   ©rJ   r-   r.   rd     re   z(Task.sig_deep_inputs.<locals>.<listcomp>N)r5   rJ   r7   r9   rÕ   rÑ   r   Zh_list)r=   rº   r-   rô   r.   Úsig_deep_inputsö  s    zTask.sig_deep_inputsc                 C   s$   | j j | j| j¡}| j |¡ dS )a˜  
		Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.env` variables/values
		When overriding this method, and if scriptlet expressions are used, make sure to follow
		the code in :py:meth:`waflib.Task.Task.compile_sig_vars` to enable dependencies on scriptlet results.

		This method may be replaced on subclasses by the metaclass to force dependencies on scriptlet code.
		N)r5   rJ   Zhash_env_varsr6   r   rÕ   rÑ   )r=   rë   r-   r-   r.   r!     s    zTask.sig_varsNc                 C   sX  | j j}|  ¡ }|j |g ¡}|r¾z||  ¡ kr6|W S W nr tjyN   ‚ Y n^ tyª   |j	 |  ¡ g ¡D ]8}| 
¡ sl| ¡ slz|jj|j= W ql ty¢   Y ql0 qlY n0 |j|= t d¡‚|  ¡ \|j	|< |j|< tjrøt d| |j	| |j| ¡ z|  ¡ |j|< W nH tyR   |j	 |  ¡ g ¡D ]}| ¡ s,t d|| ¡ q,‚ Y n0 dS )a¥  
		Used by :py:meth:`waflib.Task.Task.signature`; it hashes node signatures
		obtained by scanning for dependencies (:py:meth:`waflib.Task.Task.scan`).

		The exception :py:class:`waflib.Errors.TaskRescan` is thrown
		when a file has changed. In this case, the method :py:meth:`waflib.Task.Task.signature` is called
		once again, and return here to call :py:meth:`waflib.Task.Task.scan` and searching for dependencies.
		Zrescanz(deps: scanner for %s: %r; unresolved: %rzPDependency %r for %r is missing: check the task declaration and the build order!N)r5   rJ   r‚   r   rp   Úcompute_sig_implicit_depsr   rä   ÚEnvironmentErrorÚ	node_depsró   rç   ÚparentÚchildrenr%   r<   rÞ   rŒ   Zraw_depsr   ry   rz   Úwarn)r=   rJ   rê   Úprevr\   r>   r-   r-   r.   rÝ   -  s8    	


zTask.sig_implicit_depsc                 C   sB   | j j}|  ¡  | jjj |  ¡ g ¡D ]}|| ¡ ƒ q&| j  	¡ S )zé
		Used by :py:meth:`waflib.Task.Task.sig_implicit_deps` for computing the actual hash of the
		:py:class:`waflib.Node.Node` returned by the scanner.

		:return: a hash value for the implicit dependencies
		:rtype: string or bytes
		)
rÕ   rÑ   Úare_implicit_nodes_readyr5   rJ   rø   rp   r‚   rï   rÓ   )r=   rð   r>   r-   r-   r.   rö   ^  s
    zTask.compute_sig_implicit_depsc                 C   sÜ   | j j}z
|j}W n ty.   i  |_}Y n0 z||j }W n@ ty~   i  }||j< |jD ]}|jD ]}|||< qjq`Y n0 d}|j 	|  
¡ g ¡D ] }||v r–| j || ¡ d}q–|rØ| jD ]}|jsÂt d¡‚qÂdS )zÒ
		For each node returned by the scanner, see if there is a task that creates it,
		and infer the build order

		This has a low performance impact on null builds (1.86s->1.66s) thanks to caching (28s->1.86s)
		FTz	not readyN)r5   rJ   Zdct_implicit_nodesr§   Zcurrent_groupr<   Z	cur_tasksr8   rø   rp   r‚   r:   rÙ   r4   r   rä   )r=   rJ   ÚcacheZdctÚtskr\   Zmodifiedr-   r-   r.   rý   p  s*    



zTask.are_implicit_nodes_ready)5r   r/   r0   r1   r   rè   r   r¥   r®   r¯   r¬   r­   r   ZSIG_NILr   rí   r_   Ztree_weightr`   Ú	__slots__r   rE   rF   rG   rH   rT   r^   rB   rg   r{   r   r   r—   r°   rµ   r¼   rÊ   r¨   rÎ   r‚   rÖ   rØ   rÛ   rß   rì   r‰   rÜ   rõ   r!   rŒ   rÝ   rö   rý   r-   r-   r-   r.   r   Š   s`   		<))	!
,41r   i   c              	   C   sr   z| j W S  tyl   t | jj dd¡¡}|j}| j| j	 D ]}|| 
¡  dd¡ƒ q>| ¡ | _ | j  Y S 0 d S )Nzlatin-1Úxmlcharrefreplace)rÏ   r§   r   rÐ   r,   r   rw   rÑ   r7   r8   rÒ   rÓ   rÔ   r-   r-   r.   r‚   ’  s    
r‚   c                 C   sZ   t j}||jƒD ]}||| jƒv r dS q| jj||jƒv r@dS |jj|| jƒv rVdS dS )aC  
	Returns a non-zero value if task t1 is to be executed before task t2::

		t1.ext_out = '.h'
		t2.ext_in = '.h'
		t2.after = ['t1']
		t1.before = ['t2']
		waflib.Task.is_before(t1, t2) # True

	:param t1: Task object
	:type t1: :py:class:`waflib.Task.Task`
	:param t2: Task object
	:type t2: :py:class:`waflib.Task.Task`
	r   r   )r   Úto_listr®   r¯   r,   r   r­   r¬   )Út1Út2r  r>   r-   r-   r.   Ú	is_beforeŸ  s    r  c                 C   s®   t  t¡}t  t¡}| D ]R}|jD ]}||  |¡ q"|jD ]}||  |¡ q<|jD ]}||  |¡ qVqt| ¡ ƒ | ¡ ¡}|D ]"}|| D ]}|j	 
|| ¡ q’q†dS )z¢
	Updates the ``run_after`` attribute of all tasks based on the task inputs and outputs

	:param tasks: tasks
	:type tasks: list of :py:class:`waflib.Task.Task`
	N)r   Údefaultdictr   r7   rÙ   r9   r8   ÚkeysÚintersectionr:   rÑ   )Útasksr©   rª   r\   rÅ   Zlinksr>   r-   r-   r.   Úset_file_constraints»  s    




r
  c                   @   s*   e Zd ZdZdd„ Zdd„ ZeedƒZdS )Ú	TaskGroupz…
	Wrap nxm task order constraints into a single object
	to prevent the creation of large list/set objects

	This is an optimization
	c                 C   s   || _ || _d| _d S )NF)rü   ÚnextZdone)r=   rü   r  r-   r-   r.   r   Ù  s    zTaskGroup.__init__c                 C   s   | j D ]}|jst  S qtS r@   )rü   r4   r;   r‹   )r=   r>   r-   r-   r.   Ú
get_hasrunÞ  s    

zTaskGroup.get_hasrunN)r   r/   r0   r1   r   r  Úpropertyr4   r-   r-   r-   r.   r  Ò  s   r  c                 C   s   t  t¡}| D ]}| ¡ }||  |¡ qt| ¡ ƒ}t|ƒ}t|ƒD ]Ô}|||  d }t|d |ƒD ]°}|||  d }	t||	ƒr|}
|}nt|	|ƒrh|}
|}nqh|||
  }
|||  }t|
ƒdk sÖt|ƒdk rî|D ]}|j	 
|
¡ qÚqhtt|
ƒt|ƒƒ}|D ]}|j	 |¡ qqhqFdS )z±
	Updates the ``run_after`` attribute of all tasks based on the after/before/ext_out/ext_in attributes

	:param tasks: tasks
	:type tasks: list of :py:class:`waflib.Task.Task`
	r   r   r   N)r   r  r   r°   r¸   r  rl   Úranger  r:   rÑ   r  r   rÙ   )r	  Zcstr_groupsr\   Úhr  ZmaxiÚir  Újr  rÅ   ÚbÚgroupr-   r-   r.   Úset_precedence_constraintsæ  s2    


r  c                 C   s   i }t | |ƒ |d S )zµ
	Compiles a scriptlet expression into a Python function

	:param c: function to compile
	:type c: string
	:return: the function 'f' declared in the input string
	:rtype: function
	r(   )Úexec)ÚcZdcr-   r-   r.   Úfunex  s    	
r  z"(?P<var>\w+)|(?P<or>\|)|(?P<and>&)z^(SRC|TGT)\W+.*?$zM(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})c                    sø  g ‰‡fdd„}t  || ¡p| } g ‰‡fdd„‰ ‡ fdd„}g }|j}ˆD ]d\}}|dkrx|rn|d| ƒ n|d	ƒ qJ|d
krœ|r’|d| ƒ n|dƒ qJ|rœ| d¡rLˆ |ƒ |dd… }|dkrÐd}nj|d
krÞd}n\t |¡rúd|dd…  }n@t |¡rd|dd…  }n"ˆ |ƒ |dd… dvr:d| }|d||f ƒ nN| d¡r~t ||dd… ¡}|d||f ƒ nd||f }	ˆ |	ƒ ||	ƒ qJˆ |ƒ |d| ƒ qJ|rÈdd |¡ }nd}t| |f }
t	 
d|
 ¡  ¡ ¡ t|
ƒˆfS ) zH
	Creates a compiled function to execute a process through a sub-shell
	c                    sD   | j }|dƒrdS |dƒrdS |dƒr@ˆ  |dƒ|dƒf¡ dS d S )	NZdollarú$Z	backslashrV   ÚsubstÚvarÚcodez%s)r  r¸   )ÚmatchÚg)Úextrr-   r.   Úrepl%  s    zcompile_fun_shell.<locals>.replc                    s   | ˆ vrˆ   | ¡ d S r@   ©r¸   ©r\   ©r)   r-   r.   Úadd_dvar1  s    z#compile_fun_shell.<locals>.add_dvarc                    s:   |   d¡rdS |   d¡rdS |   d¡}ˆ |ƒ d| S d S ©NÚandz and Úorz or r  zenv[%r]©r  ©rÕ   r\   ©r$  r-   r.   Úreplc5  s    


z compile_fun_shell.<locals>.replcÚSRCztsk.inputs%sz1" ".join([a.path_from(cwdx) for a in tsk.inputs])ÚTGTztsk.outputs%sz2" ".join([a.path_from(cwdx) for a in tsk.outputs])ú:r   Nú'[a.path_from(cwdx) for a in tsk.inputs]ú([a.path_from(cwdx) for a in tsk.outputs]ú[tsk.inputs%s]r   ú[tsk.outputs%s]©rÿ   ÚgenrJ   ú%rz" ".join(tsk.colon(%r, %s))ú?zp(%r) if (%s) else ""ú%s%szp('%s')z%% (%s) z,
		r   ú
action: %s)Úreg_actÚsubr¸   Ú
startswithÚre_novarr  Úre_condrs   ÚCOMPILE_TEMPLATE_SHELLr   rz   ÚstripÚ
splitlinesr  )Úliner   r+  ZparmÚappr  ÚmethrÕ   ÚexprÚcallr  r-   )r$  r)   r  r.   Úcompile_fun_shell   s^    




rF  z[(?P<space>\s+)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})|(?P<text>([^$ \t\n\r\f\v]|\$\$)+)c                    sj  g }g ‰d}|j }‡fdd„‰ ‡ fdd„}t | ¡D ]ö}| d¡rNd}q4n²| d¡rv|d| d¡ d	d
¡ ƒ nŠ| d¡r | d¡}| d¡}|dkr¼|r°|d| ƒ n|dƒ nD|dkrâ|rÖ|d| ƒ n|dƒ n|rì| d¡r˜ˆ |ƒ |dd… }|dkrd}nn|dkr(d}n^t |¡rFd|dd…  }n@t |¡rdd|dd…  }n"ˆ |ƒ |dd… dvr†d| }|d||f ƒ nR| d¡rÊt 	||dd… ¡}|d||f ƒ n d||f }	ˆ |	ƒ |d|	 ƒ n|d| ƒ ˆ |ƒ |r(d |d! |d" f }
|d"= |
|d"< d#}q4d$d%„ |D ƒ}t
d& |¡ }t d'| ¡  ¡ ¡ t|ƒˆfS )(zH
	Creates a compiled function to execute a process without a sub-shell
	Fc                    s   | ˆ vrˆ   | ¡ d S r@   r!  r"  r#  r-   r.   r$  |  s    z%compile_fun_noshell.<locals>.add_dvarc                    s:   |   d¡rdS |   d¡rdS |   d¡}ˆ |ƒ d| S d S r%  r(  r)  r*  r-   r.   r+  €  s    


z"compile_fun_noshell.<locals>.replcZspaceÚtextz[%r]z$$r  r  r  r  r,  r1  r/  r-  r2  r0  r.  r   Nr   r3  r5  ztsk.colon(%r, %s)r6  z to_list(env[%r] if (%s) else [])r7  zto_list(%s)zto_list(env[%r])zmerge(%s, %s)r   r   Tc                 S   s   g | ]}d | ‘qS )zlst.extend(%s)r-   rb   r-   r-   r.   rd   Ã  re   z'compile_fun_noshell.<locals>.<listcomp>ú
	r8  )r¸   Úreg_act_noshellÚfinditerr  r[   r;  r<  r  r=  r:  ÚCOMPILE_TEMPLATE_NOSHELLrs   r   rz   r?  r@  r  )rA  ÚbufÚmergerB  r+  rÕ   r  r  rD  rE  r€   r*   r-   )r$  r)   r.   Úcompile_fun_noshells  sp    





rN  Fc                    s®   t | tƒr:|  d¡dks4|  d¡dks4|  d¡dkr–d}n\g }g ‰ | D ]:}t |tƒrvt||ƒ\}}||7 }ˆ  |¡ qFˆ  |¡ qF‡ fdd„}||fS |r¢t| ƒS t| ƒS dS )	a  
	Parses a string expression such as '${CC} ${SRC} -o ${TGT}' and returns a pair containing:

	* The function created (compiled) for use as :py:meth:`waflib.Task.Task.run`
	* The list of variables that must cause rebuilds when *env* data is modified

	for example::

		from waflib.Task import compile_fun
		compile_fun('cxx', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}')

		def build(bld):
			bld(source='wscript', rule='echo "foo\${SRC[0].name}\bar"')

	The env variables (CXX, ..) on the task must not hold dicts so as to preserve a consistent order.
	The reserved keywords ``TGT`` and ``SRC`` represent the task input and output nodes

	ú<r   ú>z&&Tc                    s"   ˆ D ]}|| ƒ}|r|  S qd S r@   r-   )rÚ   r\   rS   ©Zfuns_lstr-   r.   Úcomposed_funé  s
    
z!compile_fun.<locals>.composed_funN)rL   rM   Úfindr   r¸   rF  rN  )rA  r   Z	dvars_lstr\   r*   r)   rR  r-   rQ  r.   r   È  s     
*
r   c                 C   sJ   g }t | ƒD ]"}|dd… dv r| d| ¡ q|rFttd |¡ ƒS dS )aÍ  
	This method produces a sig_vars method suitable for subclasses that provide
	scriptlet code in their run_str code.
	If no such method can be created, this method returns None.

	The purpose of the sig_vars method returned is to ensures
	that rebuilds occur whenever the contents of the expression changes.
	This is the case B below::

		import time
		# case A: regular variables
		tg = bld(rule='echo ${FOO}')
		tg.env.FOO = '%s' % time.time()
		# case B
		bld(rule='echo ${gen.foo}', foo='%s' % time.time())

	:param vars: env variables such as CXXFLAGS or gen.foo
	:type vars: list of string
	:return: A sig_vars method relevant for dependencies if adequate, else None
	:rtype: A function, or None in most cases
	Nr   r3  zbuf.append(%s)rH  )Úsortedr¸   r  ÚCOMPILE_TEMPLATE_SIG_VARSrs   )r   rL  r\   r-   r-   r.   r    õ  s    r    r3   c
                 C   s˜   |pg || ||	dœ}
t |tƒs(t |tƒr2||
d< n||
d< ttƒ| tf|
ƒ}|t| < |rdt |¡|_|rtt |¡|_	|r„t |¡|_
|r”t |¡|_|S )a»  
	Returns a new task subclass with the function ``run`` compiled from the line given.

	:param func: method run
	:type func: string or function
	:param vars: list of variables to hash
	:type vars: list of string
	:param color: color to use
	:type color: string
	:param shell: when *func* is a string, enable/disable the use of the shell
	:type shell: bool
	:param scan: method scan
	:type scan: function
	:rtype: :py:class:`waflib.Task.Task`
	)r   r¥   r%   r   rŒ   r   r   )rL   rM   r«   Útyper   r#   r   r  r®   r¯   r¬   r­   )r%   Úfuncr   r¥   r®   r¯   r¬   r­   r   rŒ   Úparamsr$   r-   r-   r.   Útask_factory  s(    û
rY  c                 C   s   dd„ }|| _ | S )zJ
	Task class decorator to enable rebuilds on input files task signatures
	c                 S   s   t  | ¡ t  | ¡ d S r@   )r   rÜ   rõ   ra   r-   r-   r.   rÜ   C  s    
z&deep_inputs.<locals>.sig_explicit_deps)rÜ   )r$   rÜ   r-   r-   r.   Údeep_inputs?  s    rZ  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚTaskSemaphorea0  
	Task semaphores provide a simple and efficient way of throttling the amount of
	a particular task to run concurrently. The throttling value is capped
	by the amount of maximum jobs, so for example, a `TaskSemaphore(10)`
	has no effect in a `-j2` build.

	Task semaphores are typically specified on the task class level::

		class compile(waflib.Task.Task):
			semaphore = waflib.Task.TaskSemaphore(2)
			run_str = 'touch ${TGT}'

	Task semaphores are meant to be used by the build scheduler in the main
	thread, so there are no guarantees of thread safety.
	c                 C   s   || _ tƒ | _tƒ | _dS )zD
		:param num: maximum value of concurrent tasks
		:type num: int
		N)Únumr   ÚlockingZwaiting)r=   r\  r-   r-   r.   r   \  s    zTaskSemaphore.__init__c                 C   s   t | jƒ| jkS )z?Returns True if this semaphore cannot be acquired by more tasks)rl   r]  r\  ra   r-   r-   r.   Ú	is_lockede  s    zTaskSemaphore.is_lockedc                 C   s&   |   ¡ rtd| j ƒ‚| j |¡ dS )zÔ
		Mark the semaphore as used by the given task (not re-entrant).

		:param tsk: task object
		:type tsk: :py:class:`waflib.Task.Task`
		:raises: :py:class:`IndexError` in case the resource is already acquired
		zCannot lock more %rN)r^  Ú
IndexErrorr]  rÙ   ©r=   rÿ   r-   r-   r.   Úacquirei  s    zTaskSemaphore.acquirec                 C   s   | j  |¡ dS )zË
		Mark the semaphore as unused by the given task.

		:param tsk: task object
		:type tsk: :py:class:`waflib.Task.Task`
		:raises: :py:class:`KeyError` in case the resource is not acquired by the task
		N)r]  r|   r`  r-   r-   r.   Úreleaseu  s    zTaskSemaphore.releaseN)r   r/   r0   r1   r   r^  ra  rb  r-   r-   r-   r.   r[  L  s
   	r[  )F)3r1   rN   Úrer›   ru   r„   Úwaflibr   r   r   r;   r²   rˆ   r†   r³   râ   r‹   rá   rà   rå   rã   r>  rK  rU  r#   rV  r   Úobjectr   r   Ú
hexversionr‚   r  r
  r  r  r  Úcompiler=  r<  ÚMr9  rF  rI  rN  r   r    rY  rZ  ZTaskBaser[  r-   r-   r-   r.   Ú<module>   s^   ("      


*

RU
-,
