| #!/usr/bin/env python2 |
| |
| import sys |
| print >> sys.stderr, '\n\nemmaken.py is deprecated! use "emcc"\n\n' |
| |
| ''' |
| emmaken - the emscripten make proxy tool |
| ======================================== |
| |
| Tell your build system to use this instead of the compiler, linker, ar and |
| ranlib. All the normal build commands will be sent to this script, which |
| will proxy them to the appropriate LLVM build commands, in order to |
| generate proper code for Emscripten to later process. |
| |
| For example, compilation will be translated into calls to llvm-gcc |
| with -emit-llvm, and linking will be translated into calls to llvm-link, |
| and so forth. |
| |
| emmaken is only meant to *COMPILE* source code into LLVM bitcode. It does |
| not do optimizations (in fact, it will disable -Ox flags and warn you |
| about that). The reason is that doing such optimizations early can lead |
| to bitcode that Emscripten cannot process properly, or can process but |
| not fully optimize. You can (and probably should) still run LLVM |
| optimizations though, by telling emscripten.py to do so (or run LLVM |
| opt yourself, but be careful with the parameters you pass). |
| |
| Example uses: |
| |
| * For configure, instead of ./configure, cmake, etc., run emconfiguren.py |
| with that command as an argument, for example |
| |
| emconfiguren.py ./configure [options] |
| |
| emconfiguren.py is a tiny script that just sets some environment vars |
| as a convenience. The command just shown is equivalent to |
| |
| EMMAKEN_JUST_CONFIGURE=1 RANLIB=PATH/emmaken.py AR=PATH/emmaken.py CXX=PATH/emmakenxx.py CC=PATH/emmaken.py ./configure [options] |
| |
| where PATH is the path to this file. |
| |
| EMMAKEN_JUST_CONFIGURE tells emmaken that it is being run in ./configure, |
| so it should relay everything to gcc/g++. You should not define that when |
| running make, of course. |
| |
| * With CMake, the same command will work (with cmake instead of ./configure). You may also be |
| able to do the following in your CMakeLists.txt: |
| |
| SET(CMAKE_C_COMPILER "PATH/emmaken.py") |
| SET(CMAKE_CXX_COMPILER "PATH/emmakenxx.py") |
| SET(CMAKE_LINKER "PATH/emmaken.py") |
| SET(CMAKE_CXX_LINKER "PATH/emmaken.py") |
| SET(CMAKE_C_LINK_EXECUTABLE "PATH/emmaken.py") |
| SET(CMAKE_CXX_LINK_EXECUTABLE "PATH/emmaken.py") |
| SET(CMAKE_AR "PATH/emmaken.py") |
| SET(CMAKE_RANLIB "PATH/emmaken.py") |
| |
| * For SCons the shared.py can be imported like so: |
| __file__ = str(Dir('#/project_path_to_emscripten/dummy/dummy')) |
| __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| def path_from_root(*pathelems): |
| return os.path.join(__rootpath__, *pathelems) |
| sys.path += [path_from_root('')] |
| from tools.shared import * |
| |
| For using the Emscripten compilers/linkers/etc. you can do: |
| env = Environment() |
| ... |
| env.Append(CCFLAGS = COMPILER_OPTS) |
| env.Replace(LINK = LLVM_LD) |
| env.Replace(LD = LLVM_LD) |
| TODO: Document all relevant setup changes |
| |
| After setting that up, run your build system normally. It should generate |
| LLVM instead of the normal output, and end up with .ll files that you can |
| give to Emscripten. Note that this tool doesn't run Emscripten itself. Note |
| also that you may need to do some manual fiddling later, for example to |
| link files that weren't linked, and them llvm-dis them. |
| |
| Note the appearance of emmakenxx.py instead of emmaken.py |
| for the C++ compiler. This is needed for cases where we get |
| a C++ file with a C extension, in which case CMake can be told |
| to run g++ on it despite the .c extension, see |
| |
| https://github.com/kripken/emscripten/issues/6 |
| |
| (If a similar situation occurs with ./configure, you can do the same there too.) |
| |
| emmaken can be influenced by a few environment variables: |
| |
| EMMAKEN_NO_SDK - Will tell emmaken *not* to use the emscripten headers. Instead |
| your system headers will be used. |
| |
| EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang. |
| |
| ''' |
| |
| import sys |
| import os |
| import subprocess |
| |
| print >> sys.stderr, 'emmaken.py: ', ' '.join(sys.argv) |
| |
| __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| def path_from_root(*pathelems): |
| return os.path.join(__rootpath__, *pathelems) |
| sys.path += [path_from_root('')] |
| from tools.shared import * |
| |
| # If this is a configure-type thing, just do that |
| CONFIGURE_CONFIG = os.environ.get('EMMAKEN_JUST_CONFIGURE') |
| CMAKE_CONFIG = 'CMakeFiles/cmTryCompileExec.dir' in ' '.join(sys.argv)# or 'CMakeCCompilerId' in ' '.join(sys.argv) |
| if CONFIGURE_CONFIG or CMAKE_CONFIG: |
| compiler = 'g++' if 'CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX') else 'gcc' |
| cmd = [compiler] + EMSDK_OPTS + sys.argv[1:] |
| print >> sys.stderr, 'emmaken.py, just configuring: ', cmd |
| exit(subprocess.call(cmd)) |
| |
| try: |
| #f=open('/dev/shm/tmp/waka.txt', 'a') |
| #f.write('Args: ' + ' '.join(sys.argv) + '\nCMake? ' + str(CMAKE_CONFIG) + '\n') |
| #f.close() |
| |
| if os.environ.get('EMMAKEN_COMPILER'): |
| CXX = os.environ['EMMAKEN_COMPILER'] |
| else: |
| CXX = CLANG |
| |
| CC = to_cc(CXX) |
| |
| # If we got here from a redirection through emmakenxx.py, then force a C++ compiler here |
| if os.environ.get('EMMAKEN_CXX'): |
| CC = CXX |
| |
| CC_ADDITIONAL_ARGS = COMPILER_OPTS # + ['-g']? |
| ALLOWED_LINK_ARGS = ['-f', '-help', '-o', '-print-after', '-print-after-all', '-print-before', |
| '-print-before-all', '-time-passes', '-v', '-verify-dom-info', '-version' ] |
| TWO_PART_DISALLOWED_LINK_ARGS = ['-L'] # Ignore thingsl like |-L .| |
| |
| EMMAKEN_CFLAGS = os.environ.get('EMMAKEN_CFLAGS') |
| if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ') |
| |
| # ---------------- End configs ------------- |
| |
| if len(sys.argv) == 2 and 'conftest' not in ' '.join(sys.argv): # Avoid messing with configure, see below too |
| # ranlib |
| sys.exit(0) |
| if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']: |
| # noop ar |
| sys.exit(0) |
| |
| use_cxx = True |
| use_linker = True |
| header = False # pre-compiled headers. We fake that by just copying the file |
| |
| opts = [] |
| files = [] |
| for i in range(1, len(sys.argv)): |
| arg = sys.argv[i] |
| if arg.startswith('-'): |
| opts.append(arg) |
| else: |
| files.append(arg) |
| if arg.endswith('.c'): |
| use_cxx = False |
| if arg.endswith(('.c', '.cc', '.cpp', '.dT')): |
| use_linker = False |
| if arg.endswith('.h') and sys.argv[i-1] != '-include': |
| header = True |
| use_linker = False |
| |
| if '--version' in opts: |
| use_linker = False |
| |
| if set(sys.argv[1]).issubset(set('-cruqs')): # ar |
| sys.argv = sys.argv[:1] + sys.argv[3:] + ['-o='+sys.argv[2]] |
| assert use_linker, 'Linker should be used in this case' |
| |
| if use_linker: |
| call = LLVM_LD |
| newargs = ['-disable-opt'] |
| found_o = False |
| i = 0 |
| while i < len(sys.argv)-1: |
| i += 1 |
| arg = sys.argv[i] |
| if found_o: |
| newargs.append('-o=%s' % arg) |
| found_o = False |
| continue |
| if arg.startswith('-'): |
| if arg == '-o': |
| found_o = True |
| continue |
| prefix = arg.split('=')[0] |
| if prefix in ALLOWED_LINK_ARGS: |
| newargs.append(arg) |
| if arg in TWO_PART_DISALLOWED_LINK_ARGS: |
| i += 1 |
| elif arg.endswith('.so'): |
| continue # .so's do not exist yet, in many cases |
| else: |
| # not option, so just append |
| newargs.append(arg) |
| elif not header: |
| call = CXX if use_cxx else CC |
| newargs = sys.argv[1:] |
| for i in range(len(newargs)): |
| if newargs[i].startswith('-O'): |
| print >> sys.stderr, 'emmaken.py: WARNING: Optimization flags (-Ox) are ignored in emmaken. Tell emscripten.py to do that, or run LLVM opt.' |
| newargs[i] = '' |
| newargs = [ arg for arg in newargs if arg is not '' ] + CC_ADDITIONAL_ARGS |
| newargs.append('-emit-llvm') |
| if not use_linker: |
| newargs.append('-c') |
| else: |
| print >> sys.stderr, 'Just copy.' |
| shutil.copy(sys.argv[-1], sys.argv[-2]) |
| exit(0) |
| |
| #f=open('/dev/shm/tmp/waka.txt', 'a') |
| #f.write('Calling: ' + ' '.join(newargs) + '\n\n') |
| #f.close() |
| |
| print >> sys.stderr, "Running:", call, ' '.join(newargs) |
| |
| subprocess.call([call] + newargs) |
| except Exception, e: |
| print 'Error in emmaken.py. (Is the config file %s set up properly?) Error:' % EM_CONFIG, e |
| raise |
| |