<s> import sys <EOL> import os <EOL> import copy <EOL> import distutils <EOL> import distutils . sysconfig <EOL> import re <EOL> import warnings <EOL> import errno <EOL> from subprocess import Popen , PIPE , STDOUT <EOL> from yaku . task_manager import topo_sort , build_dag , CompiledTaskGen , set_extension_hook <EOL> from yaku . sysconfig import get_configuration , detect_distutils_cc <EOL> from yaku . compiled_fun import compile_fun <EOL> from yaku . task import task_factory <EOL> from yaku . utils import ensure_dir , get_exception <EOL> from yaku . environment import Environment <EOL> from yaku . conftests import check_compiler , check_header <EOL> from yaku . tools . ctasks import apply_define <EOL> from yaku . scheduler import run_tasks <EOL> from yaku . conf import with_conf_blddir , create_file , write_log <EOL> from yaku . errors import TaskRunFailure <EOL> from yaku . _config import _OUTPUT <EOL> import yaku . tools <EOL> pylink , pylink_vars = compile_fun ( "<STR_LIT>" , "<STR_LIT>" , False ) <EOL> pycc , pycc_vars = compile_fun ( "<STR_LIT>" , "<STR_LIT>" , False ) <EOL> pycxx , pycxx_vars = compile_fun ( "<STR_LIT>" , "<STR_LIT>" , False ) <EOL> pycxxlink , pycxxlink_vars = compile_fun ( "<STR_LIT>" , "<STR_LIT>" , False ) <EOL> _SYS_TO_PYENV = { <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> } <EOL> _PYENV_REQUIRED = [ <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> ] <EOL> _SYS_TO_CCENV = { <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> } <EOL> def setup_pyext_env ( ctx , cc_type = "<STR_LIT:default>" , use_distutils = True ) : <EOL> pyenv = Environment ( ) <EOL> if use_distutils : <EOL> if cc_type == "<STR_LIT:default>" : <EOL> dist_env = get_configuration ( ) <EOL> else : <EOL> dist_env = get_configuration ( cc_type ) <EOL> print ( dist_env ) <EOL> for name , value in dist_env . items ( ) : <EOL> pyenv [ "<STR_LIT>" % name ] = value <EOL> pyenv [ "<STR_LIT>" ] . extend ( dist_env . get ( "<STR_LIT>" , [ ] ) ) <EOL> pyenv [ "<STR_LIT>" ] = "<STR_LIT>" % dist_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = dist_env [ "<STR_LIT>" ] <EOL> else : <EOL> old_env = ctx . env <EOL> ctx . env = Environment ( ) <EOL> cc_env = None <EOL> sys . path . insert ( <NUM_LIT:0> , os . path . dirname ( yaku . tools . __file__ ) ) <EOL> try : <EOL> try : <EOL> mod = __import__ ( cc_type ) <EOL> mod . setup ( ctx ) <EOL> except ImportError : <EOL> raise RuntimeError ( "<STR_LIT>" % cc_type ) <EOL> cc_env = ctx . env <EOL> finally : <EOL> sys . path . pop ( <NUM_LIT:0> ) <EOL> ctx . env = old_env <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = "<STR_LIT>" <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv [ "<STR_LIT>" ] = cc_env [ "<STR_LIT>" ] <EOL> pyenv . append ( "<STR_LIT>" , distutils . sysconfig . get_python_inc ( ) , create = True ) <EOL> if sys . platform == "<STR_LIT:win32>" : <EOL> pyenv . append ( "<STR_LIT>" , os . path . join ( sys . exec_prefix , "<STR_LIT>" ) ) <EOL> return pyenv <EOL> def pycc_hook ( self , node ) : <EOL> tasks = pycc_task ( self , node ) <EOL> self . object_tasks . extend ( tasks ) <EOL> return tasks <EOL> def pycc_task ( self , node ) : <EOL> base = self . env [ "<STR_LIT>" ] % node . name <EOL> target = node . parent . declare ( base ) <EOL> ensure_dir ( target . abspath ( ) ) <EOL> task = task_factory ( "<STR_LIT>" ) ( inputs = [ node ] , outputs = [ target ] ) <EOL> task . gen = self <EOL> task . env_vars = pycc_vars <EOL> task . env = self . env <EOL> task . func = pycc <EOL> return [ task ] <EOL> def pycxx_hook ( self , node ) : <EOL> tasks = pycxx_task ( self , node ) <EOL> self . object_tasks . extend ( tasks ) <EOL> self . has_cxx = True <EOL> return tasks <EOL> def pycxx_task ( self , node ) : <EOL> base = self . env [ "<STR_LIT>" ] % node . name <EOL> target = node . parent . declare ( base ) <EOL> ensure_dir ( target . abspath ( ) ) <EOL> task = task_factory ( "<STR_LIT>" ) ( inputs = [ node ] , outputs = [ target ] ) <EOL> task . gen = self <EOL> task . env_vars = pycxx_vars <EOL> task . env = self . env <EOL> task . func = pycxx <EOL> return [ task ] <EOL> def pylink_task ( self , name ) : <EOL> objects = [ tsk . outputs [ <NUM_LIT:0> ] for tsk in self . object_tasks ] <EOL> if len ( objects ) < <NUM_LIT:1> : <EOL> warnings . warn ( "<STR_LIT>" % name ) <EOL> def declare_target ( ) : <EOL> folder , base = os . path . split ( name ) <EOL> tmp = folder + os . path . sep + self . env [ "<STR_LIT>" ] % base <EOL> return self . bld . path . declare ( tmp ) <EOL> target = declare_target ( ) <EOL> ensure_dir ( target . abspath ( ) ) <EOL> task = task_factory ( "<STR_LIT>" ) ( inputs = objects , outputs = [ target ] ) <EOL> task . gen = self <EOL> task . func = pylink <EOL> task . env_vars = pylink_vars <EOL> self . link_task = task <EOL> return [ task ] <EOL> class PythonBuilder ( yaku . tools . Builder ) : <EOL> def clone ( self ) : <EOL> return PythonBuilder ( self . ctx ) <EOL> def __init__ ( self , ctx ) : <EOL> yaku . tools . Builder . __init__ ( self , ctx ) <EOL> def _compile ( self , task_gen , name ) : <EOL> apply_define ( task_gen ) <EOL> apply_cpppath ( task_gen ) <EOL> tasks = task_gen . process ( ) <EOL> for t in tasks : <EOL> t . env = task_gen . env <EOL> return tasks <EOL> def try_compile ( self , name , body , headers = None ) : <EOL> old_hook = set_extension_hook ( "<STR_LIT>" , pycc_task ) <EOL> try : <EOL> return with_conf_blddir ( self . ctx , name , body , <EOL> lambda : yaku . tools . try_task_maker ( self . ctx , self . _compile , name , body , headers ) ) <EOL> finally : <EOL> set_extension_hook ( "<STR_LIT>" , old_hook ) <EOL> def try_extension ( self , name , body , headers = None ) : <EOL> old_hook = set_extension_hook ( "<STR_LIT>" , pycc_task ) <EOL> try : <EOL> return with_conf_blddir ( self . ctx , name , body , <EOL> lambda : yaku . tools . try_task_maker ( self . ctx , self . _extension , name , body , headers ) ) <EOL> finally : <EOL> set_extension_hook ( "<STR_LIT>" , old_hook ) <EOL> def _extension ( self , task_gen , name ) : <EOL> bld = self . ctx <EOL> base = name . replace ( "<STR_LIT:.>" , os . sep ) <EOL> tasks = [ ] <EOL> old_hook = set_extension_hook ( "<STR_LIT>" , pycc_hook ) <EOL> old_hook_cxx = set_extension_hook ( "<STR_LIT>" , pycxx_hook ) <EOL> apply_define ( task_gen ) <EOL> apply_cpppath ( task_gen ) <EOL> apply_libpath ( task_gen ) <EOL> apply_libs ( task_gen ) <EOL> apply_frameworks ( task_gen ) <EOL> tasks = task_gen . process ( ) <EOL> ltask = pylink_task ( task_gen , base ) <EOL> task_gen . link_task = ltask <EOL> if task_gen . has_cxx : <EOL> task_gen . link_task [ - <NUM_LIT:1> ] . func = pycxxlink <EOL> task_gen . link_task [ - <NUM_LIT:1> ] . env_vars = pycxxlink_vars <EOL> tasks . extend ( ltask ) <EOL> for t in tasks : <EOL> t . env = task_gen . env <EOL> set_extension_hook ( "<STR_LIT>" , old_hook ) <EOL> set_extension_hook ( "<STR_LIT>" , old_hook_cxx ) <EOL> return tasks <EOL> def extension ( self , name , sources , env = None ) : <EOL> sources = self . to_nodes ( sources ) <EOL> task_gen = CompiledTaskGen ( "<STR_LIT>" , self . ctx , sources , name ) <EOL> task_gen . bld = self . ctx <EOL> task_gen . env = yaku . tools . _merge_env ( self . env , env ) <EOL> tasks = self . _extension ( task_gen , name ) <EOL> self . ctx . tasks . extend ( tasks ) <EOL> outputs = [ ] <EOL> for t in task_gen . link_task : <EOL> outputs . extend ( t . outputs ) <EOL> task_gen . outputs = outputs <EOL> return tasks <EOL> def try_extension ( self , name , body , headers = None ) : <EOL> return with_conf_blddir ( self . ctx , name , body , <EOL> lambda : yaku . tools . try_task_maker ( self . ctx , self . _extension , name , body , headers ) ) <EOL> def configure ( self , candidates = None , use_distutils = True ) : <EOL> ctx = self . ctx <EOL> if candidates is None : <EOL> compiler_type = "<STR_LIT:default>" <EOL> else : <EOL> compiler_type = candidates [ <NUM_LIT:0> ] <EOL> if use_distutils : <EOL> dist_env = setup_pyext_env ( ctx , compiler_type ) <EOL> ctx . env . update ( dist_env ) <EOL> cc_exec = get_distutils_cc_exec ( ctx , compiler_type ) <EOL> yaku_cc_type = detect_cc_type ( ctx , cc_exec ) <EOL> if yaku_cc_type is None : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> _setup_compiler ( ctx , yaku_cc_type ) <EOL> cxx_exec = get_distutils_cxx_exec ( ctx , compiler_type ) <EOL> yaku_cxx_type = detect_cxx_type ( ctx , cxx_exec ) <EOL> if yaku_cxx_type is None : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> _setup_cxxcompiler ( ctx , yaku_cxx_type ) <EOL> else : <EOL> dist_env = setup_pyext_env ( ctx , compiler_type , False ) <EOL> ctx . env . update ( dist_env ) <EOL> _setup_compiler ( ctx , compiler_type ) <EOL> pycode = r"""<STR_LIT>""" <EOL> ctx . start_message ( "<STR_LIT>" % compiler_type ) <EOL> try : <EOL> self . try_compile ( "<STR_LIT:foo>" , pycode ) <EOL> ctx . end_message ( "<STR_LIT:yes>" ) <EOL> except TaskRunFailure : <EOL> e = get_exception ( ) <EOL> ctx . end_message ( "<STR_LIT>" ) <EOL> ctx . fail_configuration ( str ( e ) ) <EOL> ctx . start_message ( "<STR_LIT>" % compiler_type ) <EOL> try : <EOL> self . try_extension ( "<STR_LIT:foo>" , pycode ) <EOL> ctx . end_message ( "<STR_LIT:yes>" ) <EOL> except TaskRunFailure : <EOL> e = get_exception ( ) <EOL> ctx . end_message ( "<STR_LIT>" ) <EOL> ctx . fail_configuration ( str ( e ) ) <EOL> self . configured = True <EOL> def get_builder ( ctx ) : <EOL> return PythonBuilder ( ctx ) <EOL> CC_SIGNATURE = { <EOL> "<STR_LIT>" : re . compile ( "<STR_LIT>" ) , <EOL> "<STR_LIT>" : re . compile ( "<STR_LIT>" ) , <EOL> "<STR_LIT>" : re . compile ( "<STR_LIT>" ) <EOL> } <EOL> def detect_cc_type ( ctx , cc_cmd ) : <EOL> return _detect_cc_type ( ctx , cc_cmd ) <EOL> def detect_cxx_type ( ctx , cxx_cmd ) : <EOL> cxx_type = _detect_cc_type ( ctx , cxx_cmd ) <EOL> if cxx_type == "<STR_LIT>" : <EOL> return "<STR_LIT>" <EOL> else : <EOL> return cxx_type <EOL> def _detect_cc_type ( ctx , cc_cmd ) : <EOL> cc_type = None <EOL> def detect_type ( vflag ) : <EOL> cmd = cc_cmd + [ vflag ] <EOL> env = os . environ <EOL> env [ "<STR_LIT>" ] = env [ "<STR_LIT>" ] = "<STR_LIT:C>" <EOL> p = Popen ( cmd , stdout = PIPE , stderr = STDOUT , env = env ) <EOL> out = p . communicate ( ) [ <NUM_LIT:0> ] . decode ( ) <EOL> for k , v in CC_SIGNATURE . items ( ) : <EOL> m = v . search ( out ) <EOL> if m : <EOL> return k <EOL> return None <EOL> _OUTPUT . write ( "<STR_LIT>" ) <EOL> if sys . platform == "<STR_LIT:win32>" : <EOL> for v in [ "<STR_LIT>" , "<STR_LIT>" ] : <EOL> cc_type = detect_type ( v ) <EOL> else : <EOL> try : <EOL> for v in [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] : <EOL> cc_type = detect_type ( v ) <EOL> if cc_type : <EOL> break <EOL> if cc_type is None : <EOL> cc_type = "<STR_LIT>" <EOL> except OSError : <EOL> e = extract_exception ( ) <EOL> if e . errno == errno . ENOENT : <EOL> raise ValueError ( "<STR_LIT>" % "<STR_LIT:U+0020>" . join ( cc_cmd ) ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" % ( e , cc_cmd ) ) <EOL> _OUTPUT . write ( "<STR_LIT>" % cc_type ) <EOL> return cc_type <EOL> def get_distutils_cc_exec ( ctx , compiler_type = "<STR_LIT:default>" ) : <EOL> from distutils import ccompiler <EOL> from distutils . sysconfig import customize_compiler <EOL> _OUTPUT . write ( "<STR_LIT>" ) <EOL> if compiler_type == "<STR_LIT:default>" : <EOL> compiler_type = distutils . ccompiler . get_default_compiler ( ) <EOL> compiler = ccompiler . new_compiler ( compiler = compiler_type ) <EOL> customize_compiler ( compiler ) <EOL> if compiler_type == "<STR_LIT>" : <EOL> compiler . initialize ( ) <EOL> cc = [ compiler . cc ] <EOL> else : <EOL> cc = compiler . compiler_so [ : <NUM_LIT:1> ] <EOL> _OUTPUT . write ( "<STR_LIT>" % "<STR_LIT:U+0020>" . join ( cc ) ) <EOL> return cc <EOL> def get_distutils_cxx_exec ( ctx , compiler_type = "<STR_LIT:default>" ) : <EOL> from distutils import ccompiler <EOL> from distutils . sysconfig import customize_compiler <EOL> _OUTPUT . write ( "<STR_LIT>" ) <EOL> if compiler_type == "<STR_LIT:default>" : <EOL> compiler_type = distutils . ccompiler . get_default_compiler ( ) <EOL> compiler = ccompiler . new_compiler ( compiler = compiler_type ) <EOL> if compiler_type == "<STR_LIT>" : <EOL> compiler . initialize ( ) <EOL> cc = [ compiler . cc ] <EOL> else : <EOL> customize_compiler ( compiler ) <EOL> cc = compiler . compiler_cxx <EOL> _OUTPUT . write ( "<STR_LIT>" % "<STR_LIT:U+0020>" . join ( cc ) ) <EOL> return cc <EOL> def _setup_compiler ( ctx , cc_type ) : <EOL> old_env = ctx . env <EOL> ctx . env = Environment ( ) <EOL> cc_env = None <EOL> sys . path . insert ( <NUM_LIT:0> , os . path . dirname ( yaku . tools . __file__ ) ) <EOL> try : <EOL> try : <EOL> mod = __import__ ( cc_type ) <EOL> mod . setup ( ctx ) <EOL> except ImportError : <EOL> raise RuntimeError ( "<STR_LIT>" % cc_type ) <EOL> cc_env = ctx . env <EOL> finally : <EOL> sys . path . pop ( <NUM_LIT:0> ) <EOL> ctx . env = old_env <EOL> copied_values = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" ] <EOL> for k in copied_values : <EOL> ctx . env [ "<STR_LIT>" % k ] = cc_env [ k ] <EOL> ctx . env . prextend ( "<STR_LIT>" , cc_env [ "<STR_LIT>" ] ) <EOL> ctx . env . prextend ( "<STR_LIT>" , cc_env [ "<STR_LIT>" ] ) <EOL> def _setup_cxxcompiler ( ctx , cxx_type ) : <EOL> old_env = ctx . env <EOL> ctx . env = Environment ( ) <EOL> sys . path . insert ( <NUM_LIT:0> , os . path . dirname ( yaku . tools . __file__ ) ) <EOL> try : <EOL> mod = __import__ ( cxx_type ) <EOL> mod . setup ( ctx ) <EOL> cxx_env = ctx . env <EOL> finally : <EOL> sys . path . pop ( <NUM_LIT:0> ) <EOL> ctx . env = old_env <EOL> for k in [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" ] : <EOL> ctx . env [ "<STR_LIT>" % k ] = cxx_env [ k ] <EOL> def apply_frameworks ( task_gen ) : <EOL> if sys . platform == "<STR_LIT>" : <EOL> frameworks = task_gen . env . get ( "<STR_LIT>" , [ ] ) <EOL> task_gen . env [ "<STR_LIT>" ] = [ ] <EOL> for framework in frameworks : <EOL> task_gen . env [ "<STR_LIT>" ] . extend ( [ "<STR_LIT>" , framework ] ) <EOL> else : <EOL> task_gen . env [ "<STR_LIT>" ] = [ ] <EOL> def apply_libs ( task_gen ) : <EOL> libs = task_gen . env [ "<STR_LIT>" ] <EOL> task_gen . env [ "<STR_LIT>" ] = [ <EOL> task_gen . env [ "<STR_LIT>" ] % lib for lib in libs ] <EOL> def apply_libpath ( task_gen ) : <EOL> libdir = task_gen . env [ "<STR_LIT>" ] <EOL> implicit_paths = [ ] <EOL> libdir = list ( implicit_paths ) + libdir <EOL> task_gen . env [ "<STR_LIT>" ] = [ <EOL> task_gen . env [ "<STR_LIT>" ] % d for d in libdir ] <EOL> def apply_cpppath ( task_gen ) : <EOL> cpppaths = task_gen . env [ "<STR_LIT>" ] <EOL> implicit_paths = set ( [ s . parent . srcpath ( ) for s in task_gen . sources ] ) <EOL> srcnode = task_gen . sources [ <NUM_LIT:0> ] . ctx . srcnode <EOL> relcpppaths = [ ] <EOL> for p in cpppaths : <EOL> if not os . path . isabs ( p ) : <EOL> node = srcnode . find_node ( p ) <EOL> assert node is not None , "<STR_LIT>" % p <EOL> relcpppaths . append ( node . bldpath ( ) ) <EOL> else : <EOL> relcpppaths . append ( p ) <EOL> cpppaths = list ( implicit_paths ) + relcpppaths <EOL> task_gen . env [ "<STR_LIT>" ] = [ <EOL> task_gen . env [ "<STR_LIT>" ] % p <EOL> for p in cpppaths ] </s>
