WebAssembly
Source: examples/wasm/
Cross-compile Fortran to WebAssembly using Emscripten.
Prerequisites
Add emsdk to your MODULE.bazel:
starlark
bazel_dep(name = "emsdk", version = "4.0.17")3.A. Hello World
wasm/
├── BUILD.bazel
└── hello.f90fortran
program hello
implicit none
print *, "Hello from wasm32 with rules_fortran!"
end program hellostarlark
fortran_library(
name = "hello",
srcs = ["hello.f90"],
)
cc_binary(
name = "hello_cc",
srcs = [],
deps = [":hello"],
)
wasm_cc_binary(
name = "hello_wasm",
cc_target = ":hello_cc",
outputs = ["hello_cc.js", "hello_cc.wasm"],
)bash
bazel build //wasm:hello_wasm
node bazel-bin/wasm/hello_cc.jsHello from wasm32 with rules_fortran!The cc_binary target works as a native executable. Wrapping it with wasm_cc_binary produces WebAssembly output instead.
3.B. LAPACK
wasm/
├── BUILD.bazel
└── full.cc
#include <lapacke.h>
#include <stdio.h>
int main() {
float A[9] = {1, 2, 3, 4, 5, 6, 7, 8, 10};
int ipiv[3];
int info = LAPACKE_sgetrf(LAPACK_COL_MAJOR, 3, 3, A, 3, ipiv);
printf(info ? "FAIL\n" : "OK\n");
for (int i = 0; i < 9; i++)
printf("%8.2f%c", A[i], (i+1)%3 ? ' ' : '\n');
return info;
}starlark
cc_binary(
name = "full",
srcs = ["full.c"],
deps = [
"@blas//:single",
"@lapack//:single",
"@lapacke//:single",
],
)
wasm_cc_binary(
name = "full_wasm",
cc_target = ":full",
outputs = ["full.js", "full.wasm"],
)bash
bazel build //wasm:full_wasm
node bazel-bin/wasm/full.jsOK
3.00 0.33 0.67
6.00 2.00 0.50
10.00 3.67 -0.503.C. OpenMP (pthreads)
OpenMP parallel region running in wasm32 with emscripten pthreads.
wasm/
├── BUILD.bazel
└── omp_hello.f90fortran
program omp_hello
use omp_lib
implicit none
integer :: tid, nthreads
!$omp parallel private(tid)
tid = omp_get_thread_num()
nthreads = omp_get_num_threads()
print *, "thread", tid, "of", nthreads
!$omp end parallel
end program omp_hellostarlark
fortran_library(
name = "omp_hello",
srcs = ["omp_hello.f90"],
copts = ["-fopenmp", "-pthread"],
deps = ["@libomp"],
)
cc_binary(
name = "omp_hello_cc",
srcs = [],
linkopts = ["-pthread"],
deps = [":omp_hello"],
)
wasm_cc_binary(
name = "omp_hello_wasm",
cc_target = ":omp_hello_cc",
outputs = ["omp_hello_cc.js", "omp_hello_cc.wasm"],
threads = "emscripten",
)bash
bazel build //wasm:omp_hello_wasm
node bazel-bin/wasm/omp_hello_cc.js thread 0 of 16
thread 2 of 16
thread 1 of 16
thread 3 of 16
thread 8 of 16
thread 9 of 16
thread 11 of 16
thread 7 of 16
thread 4 of 16
thread 10 of 16
thread 5 of 16
thread 12 of 16
thread 13 of 16
thread 14 of 16
thread 6 of 16
thread 15 of 16