Difference between revisions of "WebAssembly/Compiler"

From Lazarus wiki
Jump to navigationJump to search
(Add installation instructions for both WASI and embedded targets)
(Add installation instructions for MacOS.)
Line 3: Line 3:
 
== Prerequisites ==
 
== Prerequisites ==
  
The ''wasm-ld'' linker. This the linker from the LLVM project. The external assembler ''llvm-mc'' is optional, since commit bc76487b878e59133ce3c2cc19ebb13f9a9826ea, in which, the internal assembler and object writer was enabled.
+
The linker ''wasm-ld'' from the LLVM project.  
  
LLVM 11.0 and 12.0.1 are known to work.
+
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: [https://github.com/llvm/llvm-project/issues/52641]
 
LLVM 13.0.0 has a known bug when using the FPC external assembler: [https://github.com/llvm/llvm-project/issues/52641]
Line 13: Line 13:
 
Development was done, using the Fedora packages llvm-11.0.0-1.fc33.x86_64 and lld-11.0.0-1.fc33.x86_64.
 
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 20.04 ===
+
=== Ubuntu ===
  
''wasm-ld'' is part of package ''lld-12''. Install it and set a symlink:
+
Tested on Ubuntu 20.04. ''wasm-ld'' is part of package ''lld-12''. Install it and set necessary symlinks:
 
  % sudo apt install lld-12
 
  % 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-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.
 
Note: This assumes you have a $HOME/bin directory and it is in PATH.
Line 27: Line 28:
 
=== MacOS ===
 
=== MacOS ===
  
Initial tests on MacOS used llvm-11 installed with MacPorts (https://www.macports.org) and according symlinks in /opt/local/bin (wasm32-wasi-llvm-mc -> llvm-mc-mp-11 and wasm32-embedded-llvm-mc -> llvm-mc-mp-11).
+
Tested on MacOS Catalina with LLVM 11. For [https://www.macports.org 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 ==
 
== Obtaining the compiler sources ==
Line 45: Line 51:
 
If you are new to building the compiler, see [[Installing the Free Pascal Compiler]] and [[Cross compiling]].
 
If you are new to building the compiler, see [[Installing the Free Pascal Compiler]] and [[Cross compiling]].
  
[https://wasi.dev/ 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.
+
On Ubuntu and MacOS, to build the compiler and FPC units for the WASI target:
 
 
To build the compiler and FPC units for the WASI target:
 
 
  % make all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
 
  % make all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
  
On Ubuntu 20.04, after building, install (using INSTALL_PREFIX to specify a destination within your home directory):
+
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
 
  % make crossinstall OS_TARGET=wasi CPU_TARGET=wasm32 INSTALL_PREFIX=$HOME/fpcwasm
  
Make a link to the cross compiler executable ''ppcrosswasm32'':  
+
On Ubuntu and MacOS, make a link to the cross compiler executable ''ppcrosswasm32'':  
 
  % ln -sf ~/fpcwasm/lib/fpc/3.3.1/ppcrosswasm32 ~/bin/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.
 
Note: This assumes you have a $HOME/bin directory and it is in PATH.
 +
 +
[https://wasi.dev/ 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:
 
The following units have been ported for the WASI target:
Line 87: Line 93:
 
The [[TARGET_Embedded|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.
 
The [[TARGET_Embedded|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
 
  % make all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
  
On Ubuntu 20.04, after building, install (using INSTALL_PREFIX to specify a destination within your home directory):
+
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
 
  % make crossinstall OS_TARGET=embedded CPU_TARGET=wasm32 INSTALL_PREFIX=$HOME/fpcwasm
  
If you have not built and installed the WASI cross compiler, then make a link to the cross compiler executable ''ppcrosswasm32'';   
+
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
 
  % ln -sf ~/fpcwasm/lib/fpc/3.3.1/ppcrosswasm32 ~/bin/ppcrosswasm32
 
For the embedded target, you also need to link ''wasm32-embedded-wasm-ld'' to ''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.
 
Note: This assumes you have a $HOME/bin directory and it is in PATH.
Line 102: Line 106:
 
=== Using the compiler ===
 
=== 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; add these lines:
+
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:
 
<pre>
 
<pre>
 
#ifdef cpuwasm32
 
#ifdef cpuwasm32
 
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
 
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
 
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
 
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
 +
#endif
 +
</pre>
 +
 +
For MacOS, add these lines:
 +
<pre>
 +
#ifdef cpuwasm32
 +
-Fu/Users/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
 +
-Fu/Users/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
 
#endif
 
#endif
 
</pre>
 
</pre>
Line 129: Line 143:
 
#ENDIF
 
#ENDIF
 
</pre>
 
</pre>
 
Otherwise, you have to symlink ''wasm32-wasi-wasm-ld'' and/or ''wasm32-embedded-wasm-ld'' to ''wasm-ld''; and also ''wasm32-wasi-llvm-mc'' to ''llvm-mc'' if you are using the LLVM assembler.
 
  
 
=== Lazarus ===
 
=== Lazarus ===

Revision as of 14:19, 1 April 2022

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