aboutsummaryrefslogblamecommitdiffstats
path: root/build/plugins/swig.py
blob: 32a37204a60ab9835b2aff4e0b8b914c9fc9637e (plain) (tree)
1
2
3
4
5
6
7
8
         
                
         



                            


                           
                                   


                                                                                
                         
                                       




                                                                           
                                               
 














                                                                                            
                     
                          
                                                                      
                          
                             
         
                                                                                     
 

                                                
                                     
 
                                       

                                                                                   
                                     
                                            
                                                   
 

                                                                                      
                                                    
 



                                                                                                                                            






                                         
                                                               





                            



                                                                               
                                 
                                                                                                                                     
                                                                           
 


                                                                                         
                               
                                                                                                                                              
 

                                                                     
                                   


                                                                
 
                                        
                      
 
                                                


                                                                                 
 




                                                                                







                                                                                                                                                               
 

                                                                               
 













                                                                                                   
import os
import posixpath
import re

import _import_wrapper as iw
import _common as common


def init():
    iw.addrule('swg', Swig)


class Swig(iw.CustomCommand):
    def __init__(self, path, unit):
        self._tool = unit.get('SWIG_TOOL')
        self._library_dir = unit.get('SWIG_LIBRARY') or 'contrib/tools/swig/Lib'
        self._local_swig = unit.get('USE_LOCAL_SWIG') == "yes"

        self._path = path
        self._flags = ['-cpperraswarn']

        self._bindir = common.tobuilddir(unit.path())
        self._input_name = common.stripext(os.path.basename(self._path))

        relpath = os.path.relpath(os.path.dirname(self._path), unit.path())

        self._swig_lang = unit.get('SWIG_LANG')

        if self._swig_lang != 'jni_java':
            self._main_out = os.path.join(
                self._bindir,
                '' if relpath == '.' else relpath.replace('..', '__'),
                self._input_name + '_wrap.swg.c')

            if not path.endswith('.c.swg'):
                self._flags += ['-c++']
                self._main_out += 'pp'

        # lang_specific_incl_dir = 'perl5' if self._swig_lang == 'perl' else self._swig_lang
        lang_specific_incl_dir = self._swig_lang
        if self._swig_lang == 'perl':
            lang_specific_incl_dir = 'perl5'
        elif self._swig_lang in ['jni_cpp', 'jni_java']:
            lang_specific_incl_dir = 'java'
        incl_dirs = [
            "FOR", "swig",
            posixpath.join(self._library_dir, lang_specific_incl_dir),
            "FOR", "swig",
            self._library_dir
        ]
        self._incl_dirs = ['$S', '$B'] + [posixpath.join('$S', d) for d in incl_dirs]

        modname = unit.get('REALPRJNAME')
        self._flags.extend(['-module', modname])

        if not self._local_swig:
            unit.onaddincl(incl_dirs)

        if self._swig_lang == 'python':
            self._out_name = modname + '.py'
            self._flags.extend(['-interface', unit.get('MODULE_PREFIX') + modname])

        if self._swig_lang == 'perl':
            self._out_name = modname + '.pm'
            self._flags.append('-shadow')
            unit.onpeerdir(['build/platform/perl'])

        if self._swig_lang in ['jni_cpp', 'java']:
            self._out_header = os.path.splitext(self._main_out)[0] + '.h'
            if (not unit.get('USE_SYSTEM_JDK')) and (unit.get('OS_ANDROID') != "yes"):
                unit.onpeerdir(['contrib/libs/jdk'])

        self._package = 'ru.yandex.' + os.path.dirname(self._path).replace('$S/', '').replace('$B/', '').replace('/', '.').replace('-', '_')
        if self._swig_lang in ['jni_java', 'java']:
            self._out_name = os.path.splitext(os.path.basename(self._path))[0] + '.jsrc'
        elif self._swig_lang != 'jni_cpp':
            self._flags.append('-' + self._swig_lang)

    def descr(self):
        return 'SW', self._path, 'yellow'

    def flags(self):
        return self._flags

    def tools(self):
        return ['contrib/tools/swig'] if not self._tool else []

    def input(self):
        return [
            (self._path, [])
        ]

    def output(self):
        if self._swig_lang == 'jni_java':
            return [(common.join_intl_paths(self._bindir, self._out_name), [])]
        elif self._swig_lang == 'jni_cpp':
            return [(self._main_out, []), (self._out_header, [])]

        return [
            (self._main_out, []),
            (common.join_intl_paths(self._bindir, self._out_name), (['noauto', 'add_to_outs'] if self._swig_lang != 'java' else [])),
        ] + ([(self._out_header, [])] if self._swig_lang == 'java' else [])

    def output_includes(self):
        return [(self._out_header, [])] if self._swig_lang in ['java', 'jni_cpp'] else []

    def run(self, extra_args, binary):
        if self._local_swig:
            binary = self._tool
        return self.do_run_java(binary, self._path) if self._swig_lang in ['java', 'jni_cpp', 'jni_java'] else self.do_run(binary, self._path)

    def _incl_flags(self):
        return ['-I' + self.resolve_path(x) for x in self._incl_dirs]

    def do_run(self, binary, path):
        self.call([binary] + self._flags + [
            '-o', self.resolve_path(common.get(self.output, 0)),
            '-outdir', self.resolve_path(self._bindir)
        ] + self._incl_flags() + [self.resolve_path(path)])

    def do_run_java(self, binary, path):
        import tarfile

        outdir = self.resolve_path(self._bindir)
        if self._swig_lang != 'jni_cpp':
            java_srcs_dir = os.path.join(outdir, self._package.replace('.', '/'))
            if not os.path.exists(java_srcs_dir):
                os.makedirs(java_srcs_dir)

        flags = self._incl_flags()
        src = self.resolve_path(path)
        with open(src, 'r') as f:
            if not re.search(r'(?m)^%module\b', f.read()):
                flags += ['-module', os.path.splitext(os.path.basename(src))[0]]

        if self._swig_lang == 'jni_cpp':
            self.call([binary, '-c++', '-o', self._main_out, '-java', '-package', self._package] + flags + [src])
        elif self._swig_lang == 'jni_java':
            self.call([binary, '-c++', '-o', os.path.join(outdir, 'unused.cpp'), '-outdir', java_srcs_dir, '-java', '-package', self._package] + flags + [src])
        elif self._swig_lang == 'java':
            self.call([
                binary, '-c++', '-o', self._main_out, '-outdir', java_srcs_dir,
                '-java', '-package', self._package,
            ] + flags + [src])

        if self._swig_lang in ['jni_java', 'java']:
            with tarfile.open(os.path.join(outdir, self._out_name), 'a') as tf:
                tf.add(java_srcs_dir, arcname=self._package.replace('.', '/'))

        if self._swig_lang in ['jni_cpp', 'java']:
            header = os.path.splitext(self.resolve_path(self._main_out))[0] + '.h'
            if not os.path.exists(header):
                open(header, 'w').close()


def on_swig_lang_filtered_srcs(unit, *args):
    swig_lang = unit.get('SWIG_LANG')
    allowed_exts = set()
    if swig_lang == 'jni_cpp':
        allowed_exts = set(['.cpp', '.swg'])
    if swig_lang == 'jni_java':
        allowed_exts = set(['.java', '.swg'])
    args = [arg for arg in iter(args) if allowed_exts and os.path.splitext(arg)[1] in allowed_exts]
    unit.onsrcs(args)