diff --git a/.gitignore b/.gitignore index dba3c82..01b10eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,32 @@ +.classpath +.project +.settings /gradlew /gradlew.bat /.gradle /.idea /build /gradle +/compiler/bin /compiler/build /compiler/out +/emscripten-runtime/bin /emscripten-runtime/build /emscripten-runtime/out +/annotations/bin /annotations/build /annotations/out +/examples/c-simple/bin +/examples/c-simple/build /examples/rust-simple/Cargo.lock +/examples/rust-simple/bin /examples/rust-simple/build /examples/rust-simple/target /examples/rust-string/Cargo.lock +/examples/rust-string/bin /examples/rust-string/build /examples/rust-string/target /examples/rust-regex/Cargo.lock +/examples/rust-regex/bin /examples/rust-regex/build /examples/rust-regex/target diff --git a/build.gradle b/build.gradle index 83b5df1..d524f28 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,40 @@ project(':examples') { compileOnly project(':compiler') } + // C/C++ example helpers + + task cToWasm { + doFirst { + mkdir 'build' + exec { + def cFileName = fileTree(dir: 'src', includes: ['*.c']).files.iterator().next() + commandLine 'clang', '--target=wasm32-unknown-unknown-wasm', '-O3', cFileName, '-c', '-o', 'build/lib.wasm' + } + } + } + + task showCWast(type: JavaExec) { + dependsOn cToWasm + classpath configurations.compileClasspath + main = 'asmble.cli.MainKt' + doFirst { + args 'translate', 'build/lib.wasm' + } + } + + task compileCWasm(type: JavaExec) { + dependsOn cToWasm + classpath configurations.compileClasspath + main = 'asmble.cli.MainKt' + doFirst { + def outFile = 'build/wasm-classes/' + wasmCompiledClassName.replace('.', '/') + '.class' + file(outFile).parentFile.mkdirs() + args 'compile', 'build/lib.wasm', wasmCompiledClassName, '-out', outFile + } + } + + // Rust example helpers + ext.rustBuildRelease = true task rustToWasm(type: Exec) { @@ -107,6 +141,18 @@ project(':examples') { } } +project(':examples:c-simple') { + apply plugin: 'application' + ext.wasmCompiledClassName = 'asmble.generated.CSimple' + dependencies { + compile files('build/wasm-classes') + } + compileJava { + dependsOn compileCWasm + } + mainClassName = 'asmble.examples.csimple.Main' +} + project(':examples:rust-regex') { apply plugin: 'application' apply plugin: 'me.champeau.gradle.jmh' diff --git a/examples/README.md b/examples/README.md index 2d05481..02b55e9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,4 +8,10 @@ Compile Rust to WASM and then to the JVM. In order of complexity: * [rust-simple](rust-simple) * [rust-string](rust-string) -* [rust-regex](rust-regex) \ No newline at end of file +* [rust-regex](rust-regex) + +### C/C++ + +Compile C to WASM and then to the JVM. In order of complexity: + +* [c-simple](c-simple) \ No newline at end of file diff --git a/examples/c-simple/README.md b/examples/c-simple/README.md new file mode 100644 index 0000000..b1cd834 --- /dev/null +++ b/examples/c-simple/README.md @@ -0,0 +1,14 @@ +### Example: C Simple + +This shows a simple example of compiling C to WASM and then to the JVM. This is the C version of +[rust-simple](../rust-simple). + +In order to run the C or C++ examples, the latest LLVM binaries must be on the `PATH`, built with the experimental +WebAssembly target. This can be built by passing `-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly` to `cmake` when +building WebAssembly. Or it can be downloaded from a nightly build site +([this one](http://gsdview.appspot.com/wasm-llvm/builds/) was used for these examples at the time of writing). + +Everything else is basically the same as [rust-simple](../rust-simple) except with C code and using `clang`. To run +execute the following from the root `asmble` dir: + + gradlew --no-daemon :examples:c-simple:run \ No newline at end of file diff --git a/examples/c-simple/src/lib.c b/examples/c-simple/src/lib.c new file mode 100644 index 0000000..c45f40d --- /dev/null +++ b/examples/c-simple/src/lib.c @@ -0,0 +1,3 @@ +int addOne(int x) { + return x + 1; +} \ No newline at end of file diff --git a/examples/c-simple/src/main/java/asmble/examples/csimple/Main.java b/examples/c-simple/src/main/java/asmble/examples/csimple/Main.java new file mode 100644 index 0000000..a073fb3 --- /dev/null +++ b/examples/c-simple/src/main/java/asmble/examples/csimple/Main.java @@ -0,0 +1,13 @@ +package asmble.examples.csimple; + +import java.lang.invoke.MethodHandle; + +import asmble.generated.CSimple; + +class Main { + public static void main(String[] args) { + // Doesn't need memory or method table + CSimple simple = new CSimple(0, new MethodHandle[0]); + System.out.println("25 + 1 = " + simple.addOne(25)); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f637bbc..11c9a30 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,7 @@ rootProject.name = 'asmble' include 'annotations', 'compiler', 'emscripten-runtime', + 'examples:c-simple', 'examples:rust-regex', 'examples:rust-simple', 'examples:rust-string' \ No newline at end of file