Difference between revisions of "WebAssembly/Compiler"

From Lazarus wiki
Jump to navigationJump to search
m (→‎Obtaining the compiler sources: - removed repeated word "now")
(Add installation instructions for both WASI and embedded targets)
Line 15: Line 15:
 
=== Ubuntu 20.04 ===
 
=== Ubuntu 20.04 ===
  
The wasm-ld is part of package ''lld-12''. fpc searches for the tool ''wasm32-wasi-wasm-ld'' or ''wasm-ld'' depending on the -XP flag you use (see /etc/fpc.cfg):
+
''wasm-ld'' is part of package ''lld-12''. Install it and set a symlink:
  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
  
 
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.
  
 
If you need the external assembler, install the package ''llvm-12'' and set a symlink:
 
If you need the external assembler, install the package ''llvm-12'' and set a symlink:
  apt install llvm-12
+
  % sudo apt install llvm-12
  ln -sf /usr/lib/llvm-12/bin/llvm-mc ~/bin/wasm32-wasi-llvm-mc
+
  % ln -sf /usr/lib/llvm-12/bin/llvm-mc ~/bin/wasm32-wasi-llvm-mc
  
 
=== MacOS ===
 
=== MacOS ===
Line 34: Line 34:
  
 
Get the sources:
 
Get the sources:
  git clone https://gitlab.com/freepascal.org/fpc/source.git fpc
+
  % git clone https://gitlab.com/freepascal.org/fpc/source.git fpc
  
enter the directory:
+
Enter the sources directory:
  cd fpc
+
  % cd fpc
  
 
== Supported targets ==
 
== Supported targets ==
Line 43: Line 43:
 
=== WASI - The WebAssembly System Interface ===
 
=== WASI - The WebAssembly System Interface ===
  
If you are new to building the freepascal compiler, see [[Installing the Free Pascal Compiler]]
+
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.
 
[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.
  
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
  
You can install it (e.g. via ''make install ...''), which adds the cross compiler and units.
+
On Ubuntu 20.04, 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 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.
  
 
The following units have been ported for the WASI target:
 
The following units have been ported for the WASI target:
Line 81: Line 87:
 
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.
  
  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):
 +
% 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''; 
 +
% 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.
  
 
=== Using the compiler ===
 
=== Using the compiler ===
  
By default /etc/fpc.cfg contains a ''-XP$FPCTARGET-'' flag, so fpc searches for ''wasm32-wasi-wasm-ld''. If you want to search for ''wasm-ld'' instead adapt your fpc.cfg :
+
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:
 +
<pre>
 +
#ifdef cpuwasm32
 +
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
 +
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/rtl
 +
#endif
 +
</pre>
  
If your fpc.cfg has
+
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
 
<pre>
 
<pre>
 
#IFDEF FPC_CROSSCOMPILING
 
#IFDEF FPC_CROSSCOMPILING
Line 96: Line 119:
 
</pre>
 
</pre>
  
Enclose it in '''#IFNDEF CPUWASM32''' :
+
Then, insert '''#IFNDEF CPUWASM32''' :
 
<pre>
 
<pre>
 
#IFDEF FPC_CROSSCOMPILING
 
#IFDEF FPC_CROSSCOMPILING
Line 107: Line 130:
 
</pre>
 
</pre>
  
Otherwise, you have to create symlinks wasm32-wasi-llvm-mc to llvm-mc, and wasm32-wasi-wasm-ld to wasm-ld.
+
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 06:11, 28 March 2022

Instructions

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.

LLVM 11.0 and 12.0.1 are known to work.

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 20.04

wasm-ld is part of package lld-12. Install it and set a symlink:

% sudo apt install lld-12
% ln -sf /usr/lib/llvm-12/bin/wasm-ld ~/bin/wasm32-wasi-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

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).

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.

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.

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 20.04, 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 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.

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.

% 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):

% 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;

% 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.

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:

#ifdef cpuwasm32
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/home/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

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

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