B
    br                 @   s   d Z ddlZdZdZd*ddZdd Zdd	 Zd
d Zdd Zd+ddZ	d,ddZ
d-ddZd.ddZd/ddZd0ddZd1ddZd2ddZd d! Zd3d"d#Zd4d$d%Zd&d' Zd(d) ZdS )5a
  Autoconf-like configuration support

The purpose of this module is to define how a check is to be performed.

A context class is used that defines functions for carrying out the tests,
logging and messages.  The following methods and members must be present:

context.Display(msg)
    Function called to print messages that are normally displayed
    for the user.  Newlines are explicitly used.  The text should
    also be written to the logfile!

context.Log(msg)
    Function called to write to a log file.

context.BuildProg(text, ext)
    Function called to build a program, using "ext" for the file
    extension.  Must return an empty string for success, an error
    message for failure.  For reliable test results building should
    be done just like an actual program would be build, using the
    same command and arguments (including configure results so far).

context.CompileProg(text, ext)
    Function called to compile a program, using "ext" for the file
    extension.  Must return an empty string for success, an error
    message for failure.  For reliable test results compiling should be
    done just like an actual source file would be compiled, using the
    same command and arguments (including configure results so far).

context.AppendLIBS(lib_name_list)
    Append "lib_name_list" to the value of LIBS.  "lib_namelist" is
    a list of strings.  Return the value of LIBS before changing it
    (any type can be used, it is passed to SetLIBS() later.)

context.PrependLIBS(lib_name_list)
    Prepend "lib_name_list" to the value of LIBS.  "lib_namelist" is
    a list of strings.  Return the value of LIBS before changing it
    (any type can be used, it is passed to SetLIBS() later.)

context.SetLIBS(value)
    Set LIBS to "value".  The type of "value" is what AppendLIBS()
    returned.  Return the value of LIBS before changing it (any type
    can be used, it is passed to SetLIBS() later.)

context.headerfilename
    Name of file to append configure results to, usually "confdefs.h".
    The file must not exist or be empty when starting.  Empty or None
    to skip this (some tests will not work!).

context.config_h  (may be missing).
    If present, must be a string, which will be filled with the
    contents of a config_h file.

context.vardict
    Dictionary holding variables used for the tests and stores results
    from the tests, used for the build commands.  Normally contains
    "CC", "LIBS", "CPPFLAGS", etc.

context.havedict
    Dictionary holding results from the tests that are to be used
    inside a program.  Names often start with "HAVE\_".  These are zero
    (feature not present) or one (feature present).  Other variables
    may have any value, e.g., "PERLVERSION" can be a number and
    "SYSTEMNAME" a string.
    N   c             C   sX   t |\}}}|r$| d|  |S |s,d}| d|  | ||}t| |d| |S )a  
    Configure check to see if the compiler works.
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    "text" may be used to specify the code to be build.
    Returns an empty string for success, an error message for failure.
    z%s
z"
int main(void) {
    return 0;
}
z(Checking if building a %s file works... N)_lang2suffixDisplay	BuildProg_YesNoResult)contexttextlanguagelangsuffixmsgret r   -lib/python3.7/site-packages/SCons/Conftest.pyCheckBuildero   s    
r   c             C   s.   |  d d}t| d|d}t| |d| |S )a  
    Configure check for a working C compiler.

    This checks whether the C compiler, as defined in the $CC construction
    variable, can compile a C source file. It uses the current $CCCOM value
    too, so that it can test against non working flags.

    z)Checking whether the C compiler works... z"
int main(void)
{
    return 0;
}
ZCCCN)r   _check_empty_programr   )r   r   r   r   r   r   CheckCC   s
    	
r   c             C   s2   |  d d}t| d|ddd}t| |d| |S )a  
    Configure check for a working shared C compiler.

    This checks whether the C compiler, as defined in the $SHCC construction
    variable, can compile a C source file. It uses the current $SHCCCOM value
    too, so that it can test against non working flags.

    z2Checking whether the (shared) C compiler works... z!
int foo(void)
{
    return 0;
}
ZSHCCr   T)
use_sharedN)r   r   r   )r   r   r   r   r   r   	CheckSHCC   s
    	
r   c             C   s.   |  d d}t| d|d}t| |d| |S )a  
    Configure check for a working CXX compiler.

    This checks whether the CXX compiler, as defined in the $CXX construction
    variable, can compile a CXX source file. It uses the current $CXXCOM value
    too, so that it can test against non working flags.

    z+Checking whether the C++ compiler works... z"
int main(void)
{
    return 0;
}
CXXzC++N)r   r   r   )r   r   r   r   r   r   CheckCXX   s
    	
r   c             C   s2   |  d d}t| d|ddd}t| |d| |S )a  
    Configure check for a working shared CXX compiler.

    This checks whether the CXX compiler, as defined in the $SHCXX construction
    variable, can compile a CXX source file. It uses the current $SHCXXCOM value
    too, so that it can test against non working flags.

    z4Checking whether the (shared) C++ compiler works... z"
int main(void)
{
    return 0;
}
ZSHCXXzC++T)r   N)r   r   r   )r   r   r   r   r   r   
CheckSHCXX   s
    	
r   Fc             C   sN   || j ks| j | sdS t|\}}}|r.dS |r>| ||S | ||S dS )z!Return 0 on success, 1 otherwise.r   N)envr   ZCompileSharedObjectCompileProg)r   compr   r	   r   r
   r   r   r   r   r   r      s    r   c       
      C   s   | j rd| j  }nd}|s"d| }t|\}}}|rJ| d||f  |S d|||d }| d||f  | ||}	t| |	d| |d	|  |	S )
a7  
    Configure check for a function "function_name".
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    Optional "header" can be defined to define a function prototype, include a
    header file or anything else that comes before main().
    Sets HAVE_function_name in context.havedict according to the result.
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
    Returns an empty string for success, an error message for failure.
    z#include "%s" z0
#ifdef __cplusplus
extern "C"
#endif
char %s();zCannot check for %s(): %s
z
%(include)s
#include <assert.h>
%(hdr)s

#if _MSC_VER && !__INTEL_COMPILER
    #pragma function(%(name)s)
#endif

int main(void) {
#if defined (__stub_%(name)s) || defined (__stub___%(name)s)
  fail fail fail
#else
  %(name)s();
#endif

  return 0;
}
)nameincludeZhdrz!Checking for %s function %s()... HAVE_z0Define to 1 if the system has the function `%s'.)headerfilenamer   r   r   r   )
r   Zfunction_nameheaderr	   includetextr
   r   r   r   r   r   r   r   	CheckFunc   s$    
r#   c             C   s   | j rd| j  }nd}|sd}t|\}}}|rF| d||f  |S |sNd}d|||d ||d f }	| d||f  | |	|}
t| |
d	| |	d
|  |
S )a.  
    Configure check for a C or C++ header file "header_name".
    Optional "header" can be defined to do something before including the
    header file (unusual, supported for consistency).
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    Sets HAVE_header_name in context.havedict according to the result.
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS and $CPPFLAGS are set correctly.
    Returns an empty string for success, an error message for failure.
    z#include "%s"
r   z$Cannot check for header file %s: %s
z<>z%s%s
#include %s%s%s

r   r   z"Checking for %s header file %s... r   z-Define to 1 if you have the <%s> header file.)r    r   r   r   r   )r   Zheader_namer!   r	   Zinclude_quotesr"   r
   r   r   r   r   r   r   r   CheckHeader3  s&    
r$   c             C   s   | j rd| j  }nd}|sd}t|\}}}|rF| d||f  |S d|||d }	| d||f  | |	|}
t| |
d| |	d|  |
r|r| j rt| j d	}|d
||f  |  |
S )a  
    Configure check for a C or C++ type "type_name".
    Optional "header" can be defined to include a header file.
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    Sets HAVE_type_name in context.havedict according to the result.
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
    Returns an empty string for success, an error message for failure.
    z#include "%s"r   zCannot check for %s type: %s
zw
%(include)s
%(header)s

int main(void) {
  if ((%(name)s *) 0)
    return 0;
  if (sizeof (%(name)s))
    return 0;
}
)r   r!   r   zChecking for %s type %s... r   z,Define to 1 if the system has the type `%s'.aztypedef %s %s;
)r    r   r   r   r   openwriteclose)r   	type_nameZfallbackr!   r	   r"   r
   r   r   r   r   fr   r   r   	CheckTypec  s*    

r+   c             C   sj  | j rd| j  }nd}|sd}t|\}}}|rF| d||f  |S || }	|dk	r| d||f  |	d }	| |	||f |}
|
s| d t| d| |d	|  |S | d
 t| |	|
 dS n| d|  |	d | d }	| |	|\}
}yt|}W n t	k
r    d}
d}Y nX |
sL| d t| d| |d	|  |S | d
 t| |	|
 dS dS )az  This check can be used to get the size of a given type, or to check whether
    the type is of expected size.

    Arguments:
        - type : str
            the type to check
        - includes : sequence
            list of headers to include in the test code before testing the type
        - language : str
            'C' or 'C++'
        - expect : int
            if given, will test wether the type has the given number of bytes.
            If not given, will automatically find the size.

        Returns:
            status : int
                0 if the check failed, or the found size of the type if the check succeeded.z#include "%s"r   zCannot check for %s type: %s
NzChecking %s is %d bytes... z
typedef %s scons_check_type;

int main(void)
{
    static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)];
    test_array[0] = 0;

    return 0;
}
zyes
z	SIZEOF_%sz(The size of `%s', as computed by sizeof.zno
r   zChecking size of %s ... zV
#include <stdlib.h>
#include <stdio.h>
int main(void) {
    printf("%d", (int)sizeof(z));
    return 0;
}
    r   )
r    r   r   r   _Have
_LogFailedZMessageZRunProgint
ValueError)r   r)   r!   r	   Zexpectr"   r
   r   r   srcstoutsizer   r   r   CheckTypeSize  sR    








r4   c       
      C   s   | j rd| j  }nd}|sd}t|\}}}|rF| d||f  |S || }| d|  |d||f  }| ||}	t| |	d| |d|  |	S )a  Checks whether symbol is declared.

    Use the same test as autoconf, that is test whether the symbol is defined
    as a macro or can be used as an r-value.

    Arguments:
        symbol : str
            the symbol to check
        includes : str
            Optional "header" can be defined to include a header file.
        language : str
            only C and C++ supported.

    Returns:
        status : bool
            True if the check failed, False if succeeded.z#include "%s"r   z$Cannot check for declaration %s: %s
z#Checking whether %s is declared... zI
int main(void)
{
#ifndef %s
    (void) %s;
#endif
    ;
    return 0;
}
Z
HAVE_DECL_zSet to 1 if %s is defined.)r    r   r   r   r   )
r   ZsymbolZincludesr	   r"   r
   r   r   r0   r1   r   r   r   CheckDeclaration  s"    	
r5   c             C   s   t |\}}}|r(| d||f  dS | d||f  |d}t|dkrjd}| d||f  dS |d |d  }}	| jrd	| j }
nd
}
|sd
}d|
|||	d }| ||}t| |d| |d|  |S )a  
    Configure check for a C or C++ member "aggregate_member".
    Optional "header" can be defined to include a header file.
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.

    Arguments:
        aggregate_member : str
            the member to check. For example, 'struct tm.tm_gmtoff'.
        includes : str
            Optional "header" can be defined to include a header file.
        language : str
            only C and C++ supported.

    Returns the status (0 or False = Passed, True/non-zero = Failed).
    zCannot check for member %s: %s
TzChecking for %s member %s... .   z=shall contain just one dot, for example 'struct tm.tm_gmtoff'r   r   z#include "%s"r   zi
%(include)s
%(header)s

int main(void) {
  if (sizeof ((%(aggregate)s *) 0)->%(member)s)
    return 0;
})r   r!   	aggregatememberr   z.Define to 1 if the system has the member `%s`.)r   r   splitlenr    r   r   )r   Zaggregate_memberr!   r	   r
   r   r   Zfieldsr8   r9   r"   r   r   r   r   r   CheckMember<  s0    


r<   Tc	             C   s  | j rd| j  }	nd}	|sd}d|	|f }
|rR|dkrR|sF|
d|  }
|sRd| }|
d|p\d  }
|r|d}|d	kr|d
| d }n|d dkr|d
d }n|}x|D ]}t|\}}}|r| d||f  |S |r| d|||f  n| d||f  |rH|g}|r"|| |r4| |}n
| |}d| }nd}d
}| |
|}t| |||
d|  |dkr|s|s| 	| |s|S qW |S )ai  
    Configure check for a C or C++ libraries "libs".  Searches through
    the list of libraries, until one is found where the test succeeds.
    Tests if "func_name" or "call" exists in the library.  Note: if it exists
    in another library the test succeeds anyway!
    Optional "header" can be defined to include a header file.  If not given a
    default prototype for "func_name" is added.
    Optional "extra_libs" is a list of library names to be added after
    "lib_name" in the build command.  To be used for libraries that "lib_name"
    depends on.
    Optional "call" replaces the call to "func_name" in the test code.  It must
    consist of complete C statements, including a trailing ";".
    Both "func_name" and "call" arguments are optional, and in that case, just
    linking against the libs is tested.
    "language" should be "C" or "C++" and is used to select the compiler.
    Default is "C".
    Note that this uses the current value of compiler and linker flags, make
    sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly.
    Returns an empty string for success, an error message for failure.
    z#include "%s"r   z
%s
%smainz1
#ifdef __cplusplus
extern "C"
#endif
char %s();
z%s();z
int
main() {
  %s
return 0;
}

r   Nz..;z Cannot check for library %s: %s
z$Checking for %s in %s library %s... zChecking for %s library %s... ZHAVE_LIBz)Define to 1 if you have the `%s' library.)
r    findr   r   extendZ
AppendLIBSZPrependLIBSr   r   ZSetLIBS)r   ZlibsZ	func_namer!   Z
extra_libsZcallr	   Zautoaddappendr"   r   iZcalltextZlib_namer
   r   r   lZoldLIBSZsymr   r   r   r   CheckLibt  sb    








rF   c             C   s<   |  d|  | j|}|r.|  |d  n
|  d |S )z
    Configure check for a specific program.

    Check whether program prog_name exists in path.  If it is found,
    returns the path for it, otherwise returns None.
    z%Checking whether %s program exists...r>   zno
)r   r   ZWhereIs)r   Z	prog_namepathr   r   r   	CheckProg  s    
rH   c             C   s>   |rt | || | |r0| d t| || n
| d dS )a  
    Handle the result of a test with a "yes" or "no" result.

    :Parameters:
      - `ret` is the return value: empty if OK, error message when not.
      - `key` is the name of the symbol to be defined (HAVE_foo).
      - `text` is the source code of the program used for testing.
      - `comment` is the C comment to add above the line defining the symbol (the comment is automatically put inside a /\* \*/). If None, no comment is added.
    zno
zyes
N)r,   r   r-   )r   r   keyr   commentr   r   r   r     s    

r   c             C   s   |  }tdd|}|| j|< |dkr2d| }n:|dkrDd| }n(t|tr\d||f }nd|t|f }|d	k	rd
| | }nd| }| jrt| jd}|	| |
  nt| dr| j| | _d	S )a  
    Store result of a test in context.havedict and context.headerfilename.

    :Parameters:
      - `key` - is a "HAVE_abc" name.  It is turned into all CAPITALS and non-alphanumerics are replaced by an underscore.
      - `have`   - value as it should appear in the header file, include quotes when desired and escape special characters!
      - `comment` is the C comment to add above the line defining the symbol (the comment is automatically put inside a /\* \*/). If None, no comment is added.


    The value of "have" can be:
      - 1      - Feature is defined, add "#define key".
      - 0      - Feature is not defined, add "/\* #undef key \*/". Adding "undef" is what autoconf does.  Not useful for the compiler, but it shows that the test was done.
      - number - Feature is defined to this number "#define key have". Doesn't work for 0 or 1, use a string then.
      - string - Feature is defined to this string "#define key have".


    z
[^A-Z0-9_]_r   z#define %s 1
r   z/* #undef %s */
z#define %s %d
z#define %s %s
Nz

/* %s */
r>   r%   config_h)upperresubZhavedict
isinstancer.   strr    r&   r'   r(   hasattrrL   )r   rI   ZhaverJ   Zkey_uplinelinesr*   r   r   r   r,     s&    






r,   c             C   sz   t rd| d |d}t|r8|d dkr8|dd }d}x&|D ]}| d||f  |d }qBW trv| d|  dS )	zr
    Write to the log about a failed program.
    Add line numbers, so that error messages can be understood.
    zFailed program was:
r>   r?   r   Nr   z%d: %s
zError message: %s
)LogInputFilesZLogr:   r;   LogErrorMessages)r   r   r   rT   nrS   r   r   r   r-   2  s    


r-   c             C   s*   | r| dkrdS | dkrdS ddd|  fS )aa  
    Convert a language name to a suffix.
    When "lang" is empty or None C is assumed.
    Returns a tuple (lang, suffix, None) when it works.
    For an unrecognized language returns (None, None, msg).

    Where:
      - lang   = the unified language name
      - suffix = the suffix, including the leading dot
      - msg    = an error message
    )r   c)r   z.cN)zc++zC++Zcppr   Zcxx)zC++z.cppNNzUnsupported language: %sr   )r
   r   r   r   r   D  s
    r   )NN)F)NN)NNN)NNN)NNN)NN)NN)NNNNNr   T)N)N)__doc__rN   rU   rV   r   r   r   r   r   r   r#   r$   r+   r4   r5   r<   rF   rH   r   r,   r-   r   r   r   r   r   <module>Z   s2   


I 
/ 
=
g
4
8  
j

+