diff --git a/build.gradle b/build.gradle index 9ab9542..6c32e1e 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ allprojects { version '0.4.1-fl' // skips building and running for the specified examples - ext.skipExamples = ['go-simple', 'rust-regex'] + ext.skipExamples = ['c-simple', 'go-simple', 'rust-regex'] // todo disabling Rust regex is temporary because some strings in wasm code exceed the size in 65353 bytes. repositories { @@ -71,6 +71,38 @@ project(':examples') { dependencies { 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 + } + } // Go example helpers @@ -146,10 +178,31 @@ project(':examples') { } } +project(':examples:c-simple') { + if (project.name in skipExamples) { + println("[Note!] Building and runnig for ${project.name} was skipped") + test.onlyIf { false } // explicit skipping tests + compileJava.onlyIf { false } // explicit skipping compile + return + } + + apply plugin: 'application' + ext.wasmCompiledClassName = 'asmble.generated.CSimple' + dependencies { + compile files('build/wasm-classes') + } + + compileJava { + dependsOn compileCWasm + } + mainClassName = 'asmble.examples.csimple.Main' +} project(':examples:go-simple') { if (project.name in skipExamples) { println("[Note!] Building and runnig for ${project.name} was skipped") + test.onlyIf { false } // explicit skipping tests + compileJava.onlyIf { false } // explicit skipping compile return } apply plugin: 'application' @@ -164,6 +217,13 @@ project(':examples:go-simple') { } project(':examples:rust-regex') { + if (project.name in skipExamples) { + println("[Note!] Building and runnig for ${project.name} was skipped") + test.onlyIf { false } // explicit skipping tests + compileJava.onlyIf { false } // explicit skipping compile + compileTestJava.onlyIf { false } // explicit skipping compile + return + } apply plugin: 'application' apply plugin: 'me.champeau.gradle.jmh' ext.wasmCompiledClassName = 'asmble.generated.RustRegex' @@ -176,13 +236,6 @@ project(':examples:go-simple') { } mainClassName = 'asmble.examples.rustregex.Main' - // the building will run but no test and benchmarks will run - if (project.name in skipExamples) { - println("[Note!] Building and runnig for ${project.name} was skipped") - test.onlyIf { false } // explicit skipping tests - return - } - test { testLogging.showStandardStreams = true testLogging.events 'PASSED', 'SKIPPED' @@ -197,6 +250,8 @@ project(':examples:go-simple') { project(':examples:rust-simple') { if (project.name in skipExamples) { println("[Note!] Building and runnig for ${project.name} was skipped") + test.onlyIf { false } // explicit skipping tests + compileJava.onlyIf { false } // explicit skipping compile return } apply plugin: 'application' @@ -213,6 +268,8 @@ project(':examples:rust-simple') { project(':examples:rust-string') { if (project.name in skipExamples) { println("[Note!] Building and runnig for ${project.name} was skipped") + test.onlyIf { false } // explicit skipping tests + compileJava.onlyIf { false } // explicit skipping compile return } apply plugin: 'application' 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 1c8c5ad..3b6175d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name = 'asmble' include 'annotations', 'compiler', + 'examples:c-simple', 'examples:go-simple', 'examples:rust-regex', 'examples:rust-simple',