{"id":16847481,"url":"https://github.com/fabiosantoscode/require-emscripten","last_synced_at":"2025-08-03T19:16:51.966Z","repository":{"id":29282079,"uuid":"32814819","full_name":"fabiosantoscode/require-emscripten","owner":"fabiosantoscode","description":"Require emscripten'd files in node and in the browser","archived":false,"fork":false,"pushed_at":"2022-06-22T04:33:24.000Z","size":204,"stargazers_count":38,"open_issues_count":7,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-01-11T20:50:39.018Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fabiosantoscode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-24T17:43:21.000Z","updated_at":"2021-04-07T10:25:02.000Z","dependencies_parsed_at":"2022-09-12T03:20:09.911Z","dependency_job_id":null,"html_url":"https://github.com/fabiosantoscode/require-emscripten","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiosantoscode%2Frequire-emscripten","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiosantoscode%2Frequire-emscripten/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiosantoscode%2Frequire-emscripten/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabiosantoscode%2Frequire-emscripten/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabiosantoscode","download_url":"https://codeload.github.com/fabiosantoscode/require-emscripten/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234440240,"owners_count":18832971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T13:08:05.984Z","updated_at":"2025-01-17T22:42:27.331Z","avatar_url":"https://github.com/fabiosantoscode.png","language":"CoffeeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# require-emscripten\n\n[![Join the chat at https://gitter.im/fabiosantoscode/require-emscripten](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fabiosantoscode/require-emscripten?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge) [![Build Status](https://travis-ci.org/fabiosantoscode/require-emscripten.svg?branch=master)](https://travis-ci.org/fabiosantoscode/require-emscripten)\n\nRequire C/C++ (and other LLVM languages) in node and in the browser!\n\nThis will use Emscripten's `emcc` in your PATH to compile things you require() in node and turn your exported functions into callable javascript functions. Just remember that exported functions in emscripten begin with an underscore ;)\n\n# Example\n\n(test.c is in the example directory in this repo)\n```c++\n/* I am a counter */\nint foo () {\n    static int i = 0;\n    return i++;\n}\n```\n\nOpen up the node console and type:\n```js\nconst requireEmscripten = require('require-emscripten')\nconst counter = requireEmscripten(__dirname + '/example/test.c')._foo  // do NOT let node.js print the whole module to the console. It will get your CPU to 100% and take AGES\n\nconsole.log(counter())  // -\u003e 0\nconsole.log(counter())  // -\u003e 1\nconsole.log(counter())  // -\u003e 2\n```\n\n# How to install\n\n * Install and source emscripten so that `emcc` is in your PATH. Refer to their [easy instructions on how to do this](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#windows-osx-and-linux-installing-the-portable-sdk).\n * `npm install require-emscripten`\n\n# How to use\n\n * `var requireEmscripten = require('require-emscripten'); requireEmscripten('/path/to/c-things.c')`.\n * your `requireEmscripten()` call will return a Module object straight from Emscripten, it has [this API](http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#preamble-js) and any function you exported from your C code will be in it, but their name will have a leading underscore. EG: `_foo` if your function's name is `foo`.\n * You can write directives in your C/C++ files to customize the emcc command, just add a C-style comment like this: `/* require-emscripten: -O3 */` and the command gets -O3 added as an argument. To see more arguments to the `emcc` command, run `emcc --help`.\n\n# Use in the browser with browserify\n\nAdd `browerify/transform.js` in this repo to your browserify transforms. Refer to the browserify documentation to do so.\n\nIf Browserify complains about the (excellent) `ws` module not being installed, add the --ignore-missing option to your browserify incantation (Thanks @nfroidure!). This is an emscripten soft dependency which your project will probably not need, but browserify will not know this and do its job on that `require(\"ws\")` call. If your project does need it, just install it ;)\n\nThis feature of require-emscripten is really important. If it doesn't work for you or you had a hard time doing it, please file an issue and I will try to fix it.\n\n\n# API\n\n\n## var requireEmscripten = require('require-emscripten')\n\nThis loads requireEmscripten into node. Basic stuff. requireEmscripten is a function but it does have a couple of methods:\n\n\n## var myModule = requireEmscripten(__dirname + '/my-module.c'/*, options?*/);\n\nCompiles a file into JS using emscripten, then requires it. Basically `sh('emcc $filename -o $filename.requireemscripten.js'); return require(filename + '.requireemscripten.js');`\n\nYou can customize the arguments passed to `emcc` by adding special comments to your files you want to compile. You can also pass an options hash as the second argument.\n\n## myModule (a compiled Module object which you got from requireEmscripten() or require())\n\nThis is an Emscripten Module object. Refer to their docs to figure out how to work with it, but the basics are:\n\n * DO NOT let node print this to the console, unless you want node to freeze for a long time. You may do this accidentally in the node REPL if you just go in and type `requireEmscripten('/some/c/file.c')` because the REPL prints the values in it. Instead do `var myModule = ...` and you're safe.\n * Your exported functions begin with an underscore. So instead of calling `myModule.foo`, call `myModule._foo()`\n * If they're not here it means you didn't export them. In c++ this means you have to wrap them in an `extern \"C\" { ... }` thing. In rust, this means it must be marked as `#[no_mangle]` (new line) `pub extern fn`. Etc. Refer to your language's documentation to figure out how they export things to shared object libraries and this should be pretty much the same.\n\n\n## requireEmscripten(__dirname + '/my-module.c', { toBitcode: 'my-compiler --input-file $INPUT --output-llvm $OUTPUT', cliArgs: '-O2' });\n\nThe second argument to `requireEmscripten` is an object containing options. These are the same options you can pass on the top of your C/C++ files, albeit passed as a plain JS object.\n\nThe `emccExecutable` option changes the `emcc` executable. By default it just uses `emcc` from your PATH.\n\nThe `toBitcode` option denotes a command you might want to use on the file before emscripten sees it. For example, since emscripten cannot read Lisp or Rust, you can put a Rust or Clasp (LLVM Lisp) compilation command in this option. Use `$INPUT` and `$OUTPUT` in this string. They will be replaced with absolute paths to your input and output (llvm bitcode) files, respectively.\n\nThe `cliArgs` option is an array containing more CLI arguments to the `emcc` command. Examples are `-O2` to enable some optimization.\n\nPutting it all together:\n\n```js\nrequireEmscripten(__dirname + '/filename.c', {\n    emccExecutable: 'emcc',  /*\n        Your own alternate `emcc` executable */\n    toBitcode: 'command-to-turn-filename.c-into-bitcode',  /*\n        A command which turns your file into LLVM bitcode. Useful\n        to compile LLVM languages with this, because emscripten\n        only recognizes C/C++ files. Read more below. */\n    cliArgs: ['extra arguments to emcc', 'such as', '-O3']  /*\n        Pass more arguments to emcc. */\n})\n```\n\nNone of these are mandatory.\n\n# Directives to the compiler\n\nYou put these in your C/C++/whatever files.\n\n\n## `/* require-emscripten-emcc-executable: /alt/emcc */`\n\nThis changes the `emcc` executable we use. Same as the `emccExecutable` option.\n\n\n## `/* require-emscripten: ... */`\n\nUse this to add arguments to the `emcc` command. By default, require-emscripten will do \n\n    $ emcc (file-you-required) -s EXPORT_ALL=1 -s LINKABLE=1 -o (file-you-required.emscripten.js)\n\nIf you add this to the top of your C file:\n\n    /* require-emscripten: -O3 */\n\nThen the command becomes:\n\n    $ emcc (file-you-required) -s EXPORT_ALL=1 -s LINKABLE=1 -o (file-you-required.emscripten.js) -O3\n\n\n## `/* require-emscripten-to-bitcode: ... */`\n\nIf your language is not recognized by `emcc`, you need to find another way to compile it to LLVM bitcode, which emcc understands, and is a common target.\n\nTo do that, just write a command in this option and require-emscripten will execute it.\n\nSo if you're writing [rust](http://rust-lang.org) (which compiles to LLVM bitcode), you can use this directive to tell require-emscripten how to build you some rust :)\n\n\nSome variables are expanded:\n\n * `$INPUT` - The file this comment is on\n * `$OUTPUT` - The file where require-emscripten is hoping to see some LLVM bitcode.\n\nSo for example, for rust (see more in rust-example/example.js and rust-example/main.rs) put this directive on the top of the file:\n\n    /* require-emscripten-to-bitcode: rustc --crate-type lib --emit llvm-bc $INPUT -o $OUTPUT */\n\nThe above directive tells require-emscripten to run the following command before compiling:\n\n    rustc --crate-type lib --emit llvm-bc (/my/rust/file.rs) -o (/my/rust/file.rs.requireemscripten.bc)\n\nIt calls the rust compiler, tells it it's building a library and to write some bitcode. The bitcode ends up in $OUTPUT, so that require-emscripten can tell emcc to read it, and everything is well.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabiosantoscode%2Frequire-emscripten","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffabiosantoscode%2Frequire-emscripten","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffabiosantoscode%2Frequire-emscripten/lists"}