貌似用这个可以把很多语言转为 javascript

来源:互联网 发布:暗黑破坏神3官方数据库 编辑:程序博客网 时间:2024/05/16 03:33

https://github.com/kripken/emscripten


Emscripten

Emscripten is an LLVM-to-JavaScript compiler. It takes LLVM bitcode - which can be generated from C/C++, using llvm-gcc or clang, or any other language that can be converted into LLVM - and compiles that into JavaScript, which can be run on the web (or anywhere else JavaScript can run).

Links to demostutorialFAQ, etc: https://github.com/kripken/emscripten/wiki

Main project page: http://emscripten.org

Emscripten is MIT licensed, see LICENSE.txt.



Emscripten is an open source LLVM to JavaScript compiler. With it, you can compile C and C++ code into JavaScript and run it on the web. And it's easy! This tutorial will show you how to use it.

Requirements

To use Emscripten and complete this tutorial, you need a few things:

  • The Emscripten code, from github (git clone git://github.com/kripken/emscripten.git)
  • LLVM with Clang (3.1 is the officially supported version)
  • Node.js (0.5.5 or above)
  • Python 2.7

If you don't already have those things, get them now. Notes:

  • Python is probably already installed if you are on Linux or OS X.
  • Node.js and LLVM should have convenient binaries for your OS, but installing them from source is easy, just compile them in their directories, you don't need to bother with installing them systemwide (you will point Emscripten to them in the next step, where you set up directories).
  • If you are on OS X, homebrew should be able to get you LLVM and Clang. They will probably show up in /usr/bin or /usr/local/bin.
    • A complete OS X guide for getting Emscripten and all the dependencies the test suite needs is at https://gist.github.com/1974955 (note that you don't need everything there just to run this tutorial)
  • On Windows, in order to compile the C++ standard library you will need Cygwin, for make. You will need to copy .emscripten from your home dir where emscripten normally creates it, to the Cygwin home dir.
  • Emscripten assumes 32-bit building by LLVM (which makes sense for JavaScript, and is simpler than supporting multiple targets). The easiest thing is to use 32-bit LLVM, however -m32 might work on some platforms with a 64-bit build.
  • LLVM from svn is not compatible with the version we support.

Next, change directory to where you put the Emscripten code, the rest of this tutorial will assume that that is where you are running commands (or, add a path to another location if you prefer).

Before continuing, it's a good idea to make sure the requirements work. Try

clang tests/hello_world.cpp./a.out

(Add the path to clang if it isn't installed systemwide.) That uses Clang and LLVM to compile a "hello world" app and run it. The second command there should print "hello, world!". Then, test Node.js with

node tests/hello_world.js

which should also print out "hello, world!". (As before, add the path to node if it isn't installed systemwide.)

Setting up Emscripten

If you haven't run Emscripten before, run it now with

./emcc

(If you are on Windows, you might need to do "python emcc".)

"emcc" is the "Emscripten compiler frontend", an easy way to use Emscripten basically as a drop-in replacement for a standard compiler like gcc.

The first time you run emcc (or any other of the Emscripten tools), it will create a settings file at ~/.emscripten (~ is your user's home directory) and exit. You should edit that file now, changing the directory locations of LLVM and Node to the right places in your setup (specifically, edit LLVM_ROOT and NODE_JS). If those paths are not right, Emscripten will not find LLVM, Clang or Node.js and it will fail. Look at the comments in that file that explain what the settings are and which you need to change.

After setting those paths, run ./emcc again. It should do some sanity checks which test the specified paths in ~/.emscripten. If they don't all pass, you might have a typo somewhere. When everything is set up properly, running ./emcc should tell you emcc: no input files (since we didn't specify any input files), and you can proceed to the next section in this tutorial.

Running Emscripten

You can now compile your first file! First, let's build the same "hello world" C++ file from before, but this time using Emscripten:

./emcc tests/hello_world.cpp

There should now be an a.out.js file in the current directory. Run it with

node a.out.js

and it should print "hello, world!" as expected.

  • If an error occurs when running emcc, try to run it with EMCC_DEBUG=1 in the environment, which will print out information that can help pinpoint the problem.

Generating HTML

Emscripten can also generate HTML with embedded JavaScript. Try this command:

./emcc tests/hello_world_sdl.cpp -o hello.html

By specifying that the output is an HTML file, you have told Emscripten to generate a complete HTML page. In this case, the source code uses the SDL API to show a colored cube. Open the web page in your web browser to see it (it should work in any browser that supports the Canvas element.)

Using Files

Your C/C++ code can access files using the normal libc API (stdio: fopen, etc.). Try this command:

./emcc tests/hello_world_file.cpp -o hello.html --preload-file tests/hello_world_file.txt

Open hello.html in a web browser and you will see the data from a file being written out. (Note: Chrome is unable to do file:// XHRs, so for hello.html to work in that browser you need a webserver, for example python -m SimpleHTTPServer 8888 and then openlocalhost:8888/hello.html.) Open tests/hello_world_file.cpp to see the C++ source code, and tests/hello_world_file.txt to see the data. The --preload-file option will automatically preload the file before running the compiled code; this is important because loading binary data from the network cannot be done synchronously in browsers, the API is only asynchronous, and because almost all C/C++ code is synchronous, preloading is the simplest solution.

Optimizing Code

Emscripten will by default generate unoptimized code, just like gcc does. You can generate slightly-optimized code with -O1, for example

./emcc -O1 tests/hello_world.cpp

The "hello world" code here doesn't really need to be optimized, so you won't see a difference in speed when running it. But, you can look at the generated code to see the differences: -O1 applies several minor optimizations to the code (simple ones that don't increase compilation time), and removes some runtime assertions. For example, printf will have been replaced by puts in the generated code.

Note that to fully optimize code, Emscripten uses the Closure Compiler, which is a JavaScript to JavaScript optimizing compiler. Emscripten generates code that is designed to be processed correctly in Closure Compiler's advanced mode, which can not only minify but also optimize for speed in significant ways (inlining, for example). The Closure Compiler is run automatically by emcc in -O2 and above,

./emcc -O2 tests/hello_world.cpp

If you inspect the generated code now, you will see it looks very different. This is both because of the Closure Compiler and several other optimizations that are in -O2 and not -O1. Note that -O2 and above can take a long time to complete.

  • Note that Closure Compiler requires Java to be installed.

Finally, there is a higher optimization level, -O3. This applies some speculative optimizations that are potentially dangerous: Some code compiled with -O3 will not work, but code that does work will be very fast. For more information, see Optimizing-Code.

Running the Emscripten Test Suite and Benchmarks

Emscripten has an extensive test suite. You can run it with

python tests/runner.py

This will take a long time, perhaps several hours - there are many many tests! (You can make it faster by parallelizing the tests using nose, see the comment at the top of runner.py.) You can run an individual test as follows:

python tests/runner.py test_hello_world

If you want to view the generated code from that individual test, do EMCC_DEBUG=1 python tests/runner.py test_hello_world, and then you can look inside the temp directory (TEMP_DIR/emscripten_temp, where TEMP_DIR is defined in ~/.emscripten - by default it is /tmp). Note that you can use EMCC_DEBUG with emcc in general, not just with the test runner - it tells emcc to save the internal code generation stages.

Note that Node.js cannot run 100% of the tests in the suite; if you care about running them all, you should get the SpiderMonkey shell (a recent trunk version).

You can run the Emscripten benchmarks using

python tests/runner.py benchmark

This will compile a sequence of benchmarks and run them several times, reporting averaged statistics including a comparison to how fast the same code runs when compiled to a native executable.

Under the Hood

The goal in this tutorial is to show you how to use emcc to compile code to JavaScript. The commands are very simple, and normally you don't need to understand what goes on underneath. However, if you're curious or you want to do something more advanced with Emscripten, then understanding more about how it works can be useful.

Cross-Compiling

The main 'under the hood' topic to be aware of is that emcc is a cross-compiler: You are on a 'normal' OS, running native code, but using emcc you are building for a different environment, JavaScript. Other examples of cross-compiling are building for an ARM phone on an x86 desktop, etc. When cross-compiling, the thing to keep in mind is that you need to build with settings for the target platform, not the one you are currently on. For that reason, Emscripten (and other cross-compilers) ship with a complete build environment, including system headers and so forth. When you run emcc, it does not use your /usr/include directory, instead it uses the system headers bundled with Emscripten (in system/include). One thing to be aware of is if you build a project that has hardcoded includes, for example -I/usr/include/something: Using system headers that way is dangerous when you are cross-compiling, since the headers are meant for your local system, not for the platform you are actually building for.

Emscripten Options

The Emscripten compiler (the core code called by emcc that translates LLVM assembly to JavaScript) has various options, which sometimes are useful to modify. To see the options look in src/settings.js, they appear there with descriptions of what they do in comments. To modify a setting, use the -s option to emcc, for example

emcc source.cpp -s TOTAL_STACK=10000000

This invocation of emcc will generate JavaScript that sets aside a lot of space for the stack.

General Tips and Next Steps

After finishing this tutorial, here are some general tips for using Emscripten:

  • There is a lot of useful information on this wiki. In particular, you might be interested in the following pages:
    • Interacting with Code: How to communicate with the compiled code from normal handwritten JavaScript.
    • Building Projects: How to use Emscripten to build projects using their existing makefiles etc.
    • Compressing Downloads: How to compress your compiled code and data to minimize download time.
    • FAQ: Read this if you have any questions.
    • Debugging: Check here if things go wrong.
  • If the documentation is lacking for something, use the test suite. Emscripten has an extensive test suite, and everything in it works perfectly on our test machines. For example, if you want to better understand how the --pre-js option to emcc works, search for --pre-js in the test suite (tests/, and usually the result will be in tests/runner.py).
  • Use the links on the main wiki page to the Emscripten IRC channel and mailing list. When in doubt, get in touch!

原创粉丝点击