Difference between revisions of "WebAssembly/Compiler"

From Lazarus wiki
Jump to navigationJump to search
(Link to a runnable demo.)
m (Fixed macOS capitalisation throughout)
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Instructions =
+
= Prerequisites =
 
 
== Prerequisites ==
 
  
 
The linker ''wasm-ld'' from the LLVM project. LLVM 11.0 and 12.0.1 are known to work.  
 
The linker ''wasm-ld'' from the LLVM project. LLVM 11.0 and 12.0.1 are known to work.  
  
=== Fedora ===
+
== 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.
 
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 ===
+
== Ubuntu ==
  
 
Tested on Ubuntu 20.04. ''wasm-ld'' is part of package ''lld-12''. Install it and set necessary symlinks:
 
Tested on Ubuntu 20.04. ''wasm-ld'' is part of package ''lld-12''. Install it and set necessary symlinks:
Line 18: Line 16:
 
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.
  
=== MacOS ===
+
== macOS ==
  
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:
+
=== Catalina ===
 +
Tested on '''macOS Catalina''' with LLVM 11. For [https://www.macports.org MacPorts] ''wasm-ld'' is part of package ''llvm-11''; upon installation it exists as ''wasm-ld-mp-11''. Install the package and set necessary symlinks:
 
  % sudo port install llvm-11
 
  % 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-wasi-wasm-ld
Line 27: Line 26:
 
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.
  
== Obtaining the compiler sources ==
+
=== Monterey ===
 +
Tested on '''macOS Monterey 12.5.1''': wasm-ld is part of the official clang release for macOS:
 +
https://releases.llvm.org/download.html#11.1.0
 +
 
 +
Unpack it. When running wasm-ld, macOS might warn, that ldd cannot be verified. Open the System Preferences / Security / General. There should be ldd, unlock, then click Open Anyway.
 +
 
 +
== Windows 10 ==
 +
 
 +
Tested on Windows 10 Home 21H2. Download the [https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.1 LLVM 12.0.1] 64-bit Windows installer. You are encouraged to verify the GPG signature on the installer. As administrator, run the installer. Let's say you installed into C:\llvm. Enable Windows 'developer mode' if you have not done so. Then set necessary symlinks:
 +
  C:\> cd llvm\bin
 +
  C:\llvm\bin> mklink wasm32-wasi-wasm-ld.exe wasm-ld.exe
 +
  C:\llvm\bin> mklink wasm32-embedded-wasm-ld.exe wasm-ld.exe
 +
 
 +
Add C:\llvm\bin to your PATH.
 +
 
 +
= Obtaining the compiler sources =
 +
 
 +
== Linux and macOS ==
  
 
The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:
 
The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:
Line 35: Line 51:
 
  % cd fpc
 
  % cd fpc
  
== Supported targets ==
+
== Windows ==
 +
 
 +
The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:
 +
C:\Users\OnlyMe> git clone https://gitlab.com/freepascal.org/fpc/source.git fpc
 +
 
 +
Enter the sources directory:
 +
C:\Users\OnlyMe> cd fpc
 +
 
 +
= Building and installing =
  
 
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]].
  
=== WASI - The WebAssembly System Interface ===
+
FPC supports two WebAssembly compilation targets: WASI and embedded.
  
On Ubuntu and MacOS, to build the compiler and FPC units for the WASI target:
+
== Compilation target: WASI ==
% 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):
+
=== Linux and macOS ===
 +
 
 +
Build the compiler and FPC units for the WASI target:
 +
% make clean all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
 +
 
 +
Then, 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
  
On Ubuntu and MacOS, make a link to the cross compiler executable ''ppcrosswasm32'':  
+
Note: On macOS you might have to add ''-XR/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'' to ''OPT''.
 +
 
 +
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.
+
=== Windows ===
 
 
The following units have been ported for the WASI target:
 
  
* system
+
Make sure the Windows native compiler fpc.exe and the FPC-bundled make.exe are in your PATH. Especially ensure that the FPC make.exe comes first in your PATH; using another make.exe (such as the one installed by Delphi) that happens to be ahead in PATH may not work.
* 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:
+
Build the compiler and FPC units for the WASI target:
 +
C:\Users\OnlyMe\fpc> make clean all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
  
* dos
+
Then, install, using INSTALL_PREFIX to specify a destination folder:
* sysutils
+
C:\Users\OnlyMe\fpc> make crossinstall OS_TARGET=wasi CPU_TARGET=wasm32 INSTALL_PREFIX=c:\fpcwasm PP=fpc
* classes
 
* math
 
* fgl
 
  
See [[WebAssembly/Roadmap]] for details.
+
Add C:\fpcwasm\bin\x86_64-win64 to your PATH to easily run the compiler ''ppcrosswasm32.exe''.
  
Compiled WASI binaries work with modern web browsers, although they require the web browser to provide the necessary WASI runtime services. See [https://github.com/PierceNg/wasm-demo wasm-demo] for an example implementing Conway's Game of Life. In the example, WASI functions are implemented in Javascript; the functions themselves do nothing, because the Pascal code implementing Life does not use those functions - they are only 'required' because of compiler-generated linkages.
+
== Compilation target: Embedded  ==
  
=== Embedded target ===
+
=== Linux and macOS ===
  
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.
+
Build the compiler and FPC units for the 'embedded' target:
 +
% make clean all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
  
On Ubuntu and MacOS, to build the compiler and FPC units for the 'embedded' target:
+
Then, install, using INSTALL_PREFIX to specify a destination within your home directory:
% 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
 
  % 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'';   
+
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
  
 
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.
  
=== Using the compiler ===
+
=== Windows ===
  
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.
+
Make sure the Windows native compiler fpc.exe and the FPC-bundled make.exe are in your PATH. Especially ensure that the FPC make.exe comes first in your PATH; using another make.exe (such as the one installed by Delphi) that happens to be ahead in PATH may not work.
 +
 
 +
Build the compiler and FPC units for the 'embedded' target:
 +
C:\Users\OnlyMe\fpc> make clean all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
 +
 
 +
Then, install, using INSTALL_PREFIX to specify a destination folder:
 +
C:\Users\OnlyMe\fpc> make crossinstall OS_TARGET=embedded CPU_TARGET=wasm32 INSTALL_PREFIX=c:\fpcwasm PP=fpc
 +
 
 +
Add C:\fpcwasm\bin\x86_64-win64 to your PATH if you have not already done so.
 +
 
 +
= Using the compiler =
 +
 
 +
For Linux and macOS, 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:
 
For Ubuntu, add these lines:
Line 102: Line 133:
 
</pre>
 
</pre>
  
For MacOS, add these lines:
+
For macOS, add these lines:
 
<pre>
 
<pre>
 
#ifdef cpuwasm32
 
#ifdef cpuwasm32
Line 110: Line 141:
 
</pre>
 
</pre>
  
=== Lazarus ===
+
On Windows, if you have set C:\fpcwasm\bin\x86_64-win64 directory in your PATH, then ''ppcrosswasm32.exe'' will be able to find its units.
 +
 
 +
= Using the compiler with 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'':
 
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'':

Latest revision as of 13:13, 8 September 2022

Prerequisites

The linker wasm-ld from the LLVM project. LLVM 11.0 and 12.0.1 are known to work.

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.

macOS

Catalina

Tested on macOS Catalina with LLVM 11. For MacPorts wasm-ld is part of package llvm-11; upon installation it exists as wasm-ld-mp-11. Install the package and set necessary symlinks:

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

Monterey

Tested on macOS Monterey 12.5.1: wasm-ld is part of the official clang release for macOS: https://releases.llvm.org/download.html#11.1.0

Unpack it. When running wasm-ld, macOS might warn, that ldd cannot be verified. Open the System Preferences / Security / General. There should be ldd, unlock, then click Open Anyway.

Windows 10

Tested on Windows 10 Home 21H2. Download the LLVM 12.0.1 64-bit Windows installer. You are encouraged to verify the GPG signature on the installer. As administrator, run the installer. Let's say you installed into C:\llvm. Enable Windows 'developer mode' if you have not done so. Then set necessary symlinks:

 C:\> cd llvm\bin
 C:\llvm\bin> mklink wasm32-wasi-wasm-ld.exe wasm-ld.exe
 C:\llvm\bin> mklink wasm32-embedded-wasm-ld.exe wasm-ld.exe

Add C:\llvm\bin to your PATH.

Obtaining the compiler sources

Linux and macOS

The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:

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

Enter the sources directory:

% cd fpc

Windows

The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:

C:\Users\OnlyMe> git clone https://gitlab.com/freepascal.org/fpc/source.git fpc

Enter the sources directory:

C:\Users\OnlyMe> cd fpc

Building and installing

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

FPC supports two WebAssembly compilation targets: WASI and embedded.

Compilation target: WASI

Linux and macOS

Build the compiler and FPC units for the WASI target:

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

Then, install, using INSTALL_PREFIX to specify a destination within your home directory:

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

Note: On macOS you might have to add -XR/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk to OPT.

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.

Windows

Make sure the Windows native compiler fpc.exe and the FPC-bundled make.exe are in your PATH. Especially ensure that the FPC make.exe comes first in your PATH; using another make.exe (such as the one installed by Delphi) that happens to be ahead in PATH may not work.

Build the compiler and FPC units for the WASI target:

C:\Users\OnlyMe\fpc> make clean all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc

Then, install, using INSTALL_PREFIX to specify a destination folder:

C:\Users\OnlyMe\fpc> make crossinstall OS_TARGET=wasi CPU_TARGET=wasm32 INSTALL_PREFIX=c:\fpcwasm PP=fpc

Add C:\fpcwasm\bin\x86_64-win64 to your PATH to easily run the compiler ppcrosswasm32.exe.

Compilation target: Embedded

Linux and macOS

Build the compiler and FPC units for the 'embedded' target:

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

Then, 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

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

Windows

Make sure the Windows native compiler fpc.exe and the FPC-bundled make.exe are in your PATH. Especially ensure that the FPC make.exe comes first in your PATH; using another make.exe (such as the one installed by Delphi) that happens to be ahead in PATH may not work.

Build the compiler and FPC units for the 'embedded' target:

C:\Users\OnlyMe\fpc> make clean all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc

Then, install, using INSTALL_PREFIX to specify a destination folder:

C:\Users\OnlyMe\fpc> make crossinstall OS_TARGET=embedded CPU_TARGET=wasm32 INSTALL_PREFIX=c:\fpcwasm PP=fpc

Add C:\fpcwasm\bin\x86_64-win64 to your PATH if you have not already done so.

Using the compiler

For Linux and macOS, 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

On Windows, if you have set C:\fpcwasm\bin\x86_64-win64 directory in your PATH, then ppcrosswasm32.exe will be able to find its units.

Using the compiler with 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