| LEFT | RIGHT | 
| (no file at all) |  | 
|    1 #!/usr/bin/env python |  | 
|    2  |  | 
|    3 # This file is part of Adblock Plus <https://adblockplus.org/>, |  | 
|    4 # Copyright (C) 2006-present eyeo GmbH |  | 
|    5 # |  | 
|    6 # Adblock Plus is free software: you can redistribute it and/or modify |  | 
|    7 # it under the terms of the GNU General Public License version 3 as |  | 
|    8 # published by the Free Software Foundation. |  | 
|    9 # |  | 
|   10 # Adblock Plus is distributed in the hope that it will be useful, |  | 
|   11 # but WITHOUT ANY WARRANTY; without even the implied warranty of |  | 
|   12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | 
|   13 # GNU General Public License for more details. |  | 
|   14 # |  | 
|   15 # You should have received a copy of the GNU General Public License |  | 
|   16 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |  | 
|   17  |  | 
|   18 import argparse |  | 
|   19 import os |  | 
|   20 import subprocess |  | 
|   21 import sys |  | 
|   22  |  | 
|   23 BASE_DIR = os.path.dirname(__file__) |  | 
|   24 SOURCE_DIR = os.path.join(BASE_DIR, 'compiled') |  | 
|   25 JS_LIBRARY = os.path.join(SOURCE_DIR, 'library.js') |  | 
|   26 BINDINGS_GENERATOR = os.path.join(SOURCE_DIR, 'bindings.cpp.js') |  | 
|   27 BINDINGS_OUTPUT = os.path.join(SOURCE_DIR, 'bindings.js') |  | 
|   28 COMPILER_OUTPUT = os.path.join(BASE_DIR, 'lib', 'compiled.js') |  | 
|   29 GENERATION_PARAMS = { |  | 
|   30     'SHELL_FILE': "'{}'".format(os.path.abspath(os.path.join(SOURCE_DIR, |  | 
|   31                                                              'shell.js'))), |  | 
|   32     'ASM_JS': 2,  # "almost asm" |  | 
|   33     'TOTAL_MEMORY': 16*1024*1024, |  | 
|   34     'TOTAL_STACK': 1*1024*1024, |  | 
|   35     'ALLOW_MEMORY_GROWTH': 1, |  | 
|   36     'NO_EXIT_RUNTIME': 1, |  | 
|   37     'NO_DYNAMIC_EXECUTION': 1, |  | 
|   38     'NO_FILESYSTEM': 1, |  | 
|   39     'INVOKE_RUN': 0, |  | 
|   40     'TEXTDECODER': 0, |  | 
|   41     'EXPORTED_RUNTIME_METHODS': ['cwrap', 'ccall', 'stringToAscii'], |  | 
|   42 } |  | 
|   43 DEFINES = [] |  | 
|   44 ADDITIONAL_PARAMS = ['-O3', '-m32', '-std=c++1z', '--memory-init-file', '0', |  | 
|   45                      '--emit-symbol-map', '-Wall', '-Werror', '-fno-exceptions', |  | 
|   46                      '-fno-rtti', '--js-library', JS_LIBRARY] |  | 
|   47  |  | 
|   48  |  | 
|   49 def get_source_files(phase): |  | 
|   50     for (path, dirs, files) in os.walk(SOURCE_DIR): |  | 
|   51         for f in files: |  | 
|   52             if os.path.splitext(f)[1] != '.cpp': |  | 
|   53                 continue |  | 
|   54             if ( |  | 
|   55                 phase != 'bindings' and |  | 
|   56                 os.path.basename(path) == 'bindings' and |  | 
|   57                 not f.startswith('runtime_') |  | 
|   58             ): |  | 
|   59                 continue |  | 
|   60             yield os.path.join(path, f) |  | 
|   61  |  | 
|   62 def getenv(emscripten_config): |  | 
|   63     scope = {} |  | 
|   64     execfile(emscripten_config, scope, scope) |  | 
|   65     env = os.environ.copy() |  | 
|   66     env.update({ |  | 
|   67         'EM_CONFIG': emscripten_config, |  | 
|   68         'EMSCRIPTEN': scope['EMSCRIPTEN_ROOT'], |  | 
|   69         'PYTHON': scope.get('PYTHON', sys.executable), |  | 
|   70         'NODE_JS': scope.get('NODE_JS', 'node'), |  | 
|   71     }) |  | 
|   72     return env |  | 
|   73  |  | 
|   74  |  | 
|   75 def generate_bindings(env): |  | 
|   76     params = [ |  | 
|   77         env['PYTHON'], os.path.join(env['EMSCRIPTEN'], 'emcc'), |  | 
|   78         '-o', BINDINGS_GENERATOR, '-std=c++1z', '--js-library', JS_LIBRARY, |  | 
|   79         '--js-library', os.path.join(SOURCE_DIR, 'bindings', 'library.js'), |  | 
|   80     ] + list(get_source_files('bindings')) |  | 
|   81     subprocess.check_call(params, env=env) |  | 
|   82  |  | 
|   83     with open(BINDINGS_OUTPUT, 'w') as file: |  | 
|   84         subprocess.check_call([env['NODE_JS'], BINDINGS_GENERATOR], |  | 
|   85                               stdout=file) |  | 
|   86  |  | 
|   87  |  | 
|   88 def run_compiler(env, debug=False, tracing=False): |  | 
|   89     params = [ |  | 
|   90         env['PYTHON'], os.path.join(env['EMSCRIPTEN'], 'emcc'), |  | 
|   91         '-o', COMPILER_OUTPUT, |  | 
|   92         '--post-js', BINDINGS_OUTPUT, |  | 
|   93     ] |  | 
|   94     # Order matters. We sort source files so that we always get the same |  | 
|   95     # results for the same source code. |  | 
|   96     params.extend(sorted(get_source_files('compile'))) |  | 
|   97     params.extend('-D' + flag for flag in DEFINES) |  | 
|   98     for key, value in GENERATION_PARAMS.iteritems(): |  | 
|   99         params.extend(['-s', '{}={}'.format(key, str(value))]) |  | 
|  100     if debug: |  | 
|  101         params.append('-DDEBUG') |  | 
|  102         params.append('-g3') |  | 
|  103     if tracing: |  | 
|  104         params.append('--tracing') |  | 
|  105     params.extend(ADDITIONAL_PARAMS) |  | 
|  106     subprocess.check_call(params, env=env) |  | 
|  107  |  | 
|  108  |  | 
|  109 if __name__ == '__main__': |  | 
|  110     parser = argparse.ArgumentParser( |  | 
|  111         description='Compile Emscripten-based C++ code to JavaScript' |  | 
|  112     ) |  | 
|  113     parser.add_argument( |  | 
|  114         '--emscripten-config', |  | 
|  115         metavar='DIR', |  | 
|  116         default=os.path.expanduser('~/.emscripten'), |  | 
|  117         help='Emscripten installation directory' |  | 
|  118     ) |  | 
|  119     parser.add_argument( |  | 
|  120         '-d', '--debug', |  | 
|  121         action='store_true', |  | 
|  122         help='Disable code minification' |  | 
|  123     ) |  | 
|  124     parser.add_argument( |  | 
|  125         '-t', '--tracing', |  | 
|  126         action='store_true', |  | 
|  127         help='Enable memory tracing' |  | 
|  128     ) |  | 
|  129     args = parser.parse_args() |  | 
|  130  |  | 
|  131     env = getenv(args.emscripten_config) |  | 
|  132     generate_bindings(env) |  | 
|  133     run_compiler(env, debug=args.debug, tracing=args.tracing) |  | 
| LEFT | RIGHT |