WebAssembly/Compiler

From Free Pascal wiki
Revision as of 14:19, 1 April 2022 by PierceNg (talk | contribs) (Add installation instructions for MacOS.)
Jump to navigationJump to search

Instructions

Prerequisites

The linker wasm-ld from the LLVM project.

The external assembler llvm-mc is optional, since commit bc76487b878e59133ce3c2cc19ebb13f9a9826ea, in which, the internal assembler and object writer was enabled.

LLVM 13.0.0 has a known bug when using the FPC external assembler: [1]

Fedora

Development was done, using the Fedora packages llvm-11.0.0-1.fc33.x86_64 and lld-11.0.0-1.fc33.x86_64.

Ubuntu

Tested on Ubuntu 20.04. wasm-ld is part of package lld-12. Install it and set necessary symlinks:

% sudo apt install lld-12
% ln -sf /usr/lib/llvm-12/bin/wasm-ld ~/bin/wasm32-wasi-wasm-ld
% ln -sf /usr/lib/llvm-12/bin/wasm-ld ~/bin/wasm32-embedded-wasm-ld

Note: This assumes you have a $HOME/bin directory and it is in PATH.

If you need the external assembler, install the package llvm-12 and set a symlink:

% sudo apt install llvm-12
% ln -sf /usr/lib/llvm-12/bin/llvm-mc ~/bin/wasm32-wasi-llvm-mc

MacOS

Tested on MacOS Catalina with LLVM 11. For MacPorts, wasm-ld is part of package llvm-11. Install it and set necessary symlink:

% sudo port install llvm-11
% ln -sf /opt/local/bin/wasm-ld-mp-11 ~/bin/wasm32-wasi-wasm-ld
% ln -sf /opt/local/bin/wasm-ld-mp-11 ~/bin/wasm32-embedded-wasm-ld

Note: This assumes you have a $HOME/bin directory and it is in PATH.

Obtaining the compiler sources

The WebAssembly target was merged into FPC SVN trunk in r48955 on 2021-03-14. Since then, Free Pascal has moved to GitLab, so now it's included in the git 'main' branch.

Get the sources:

% git clone https://gitlab.com/freepascal.org/fpc/source.git fpc

Enter the sources directory:

% cd fpc

Supported targets

WASI - The WebAssembly System Interface

If you are new to building the compiler, see Installing the Free Pascal Compiler and Cross compiling.

On Ubuntu and MacOS, to build the compiler and FPC units for the WASI target:

% make all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc

On Ubuntu and MacOS, after building, install (using INSTALL_PREFIX to specify a destination within your home directory):

% make crossinstall OS_TARGET=wasi CPU_TARGET=wasm32 INSTALL_PREFIX=$HOME/fpcwasm

On Ubuntu and MacOS, make a link to the cross compiler executable ppcrosswasm32:

% ln -sf ~/fpcwasm/lib/fpc/3.3.1/ppcrosswasm32 ~/bin/ppcrosswasm32

Note: This assumes you have a $HOME/bin directory and it is in PATH.

WASI is a modular system interface for WebAssembly. It allows creating portable and secure programs that can run in a sandboxed command-line environment or in the browser. See the WASI website for more information.

The following units have been ported for the WASI target:

  • system
  • objpas
  • iso7185
  • ctypes
  • strings
  • wasiapi - interface for the WASI API

Additionally, these units compile, but are not yet fully functional and/or tested very well:

  • dos
  • sysutils
  • classes
  • math
  • fgl

See WebAssembly/Roadmap for details.

Compiled WASI binaries work with wasmtime version 0.23.0 or in the browser by opening:

https://webassembly.sh/

and drag and dropping the .wasm binary directly into the browser window.

Embedded target

The Embedded target is primarily used for embedded systems (not a browser), without an operating system. However, it also happens to be a perfect fit for creating WebAssembly modules that don't use any particular operating system-like API.

On Ubuntu and MacOS, to build the compiler and FPC units for the 'embedded' target:

% make all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc

On Ubuntu and MacOS, after building, install (using INSTALL_PREFIX to specify a destination within your home directory):

% make crossinstall OS_TARGET=embedded CPU_TARGET=wasm32 INSTALL_PREFIX=$HOME/fpcwasm

On Ubuntu and MacOS, if you have not built and installed the WASI cross compiler, then make a link to the cross compiler executable ppcrosswasm32;

% ln -sf ~/fpcwasm/lib/fpc/3.3.1/ppcrosswasm32 ~/bin/ppcrosswasm32

Note: This assumes you have a $HOME/bin directory and it is in PATH.

Using the compiler

If you have installed the cross compiler and units into $HOME/fpcwasm (as per the commands used above), then you need to configure $HOME/.fpc.cfg so that the cross compiler can locate its units.

For Ubuntu, add these lines:

#ifdef cpuwasm32
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
#endif

For MacOS, add these lines:

#ifdef cpuwasm32
-Fu/Users/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/Users/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
#endif

By default $HOME/.fpc.cfg (or /etc/fpc.cfg if that's what you use) contains a -XP$FPCTARGET- flag, so FPC searches for wasm32-wasi-wasm-ld (for the WASI OS target) or wasm32-embedded-wasm-ld (for the embedded target). If you want to search for wasm-ld instead adapt your fpc.cfg as follows: If your fpc.cfg has

#IFDEF FPC_CROSSCOMPILING
#IFDEF NEEDCROSSBINUTILS
  -XP$FPCTARGET-
#ENDIF
#ENDIF

Then, insert #IFNDEF CPUWASM32 :

#IFDEF FPC_CROSSCOMPILING
#IFDEF NEEDCROSSBINUTILS
#ifndef cpuwasm32
  -XP$FPCTARGET-
#endif
#ENDIF
#ENDIF

Lazarus

When you create a new Lazarus project for a wasm program you can use the Simple Program template and then adjust the Project / Project Options / Compiler Options:

  • Paths / Target file name: Lazarus 2.3.0 (Dec 28th 2021) appends the required .wasm file extension to the output file. To support older IDEs disable Apply conventions and set <programname>.wasm.
  • Config and Target / Target platform:
    • Target OS: Wasi
    • Target CPU: wasm32
  • Debugging / Generate info for debugger: disable (Dec 28th 2021: otherwise you will get can't find unit linfodwrf)
  • Compiler Commands / Compiler / Command: If you are using different fpc versions / folders you can here set the path to ppcrosswasm32 (e.g. Linux: /usr/lib/fpc/3.3.1/ppcrosswasm32)

See Also