Difference between revisions of "WebAssembly/Compiler"

From Free Pascal wiki
Jump to navigationJump to search
(Clarify name of wasm-ld on MacOS.)
(Add Windows instructions.)
Line 20: Line 20:
 
=== MacOS ===
 
=== MacOS ===
  
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 it and set necessary symlinks:
+
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 26: 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.
 +
 +
=== 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 ==
 
== 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 34: Line 45:
 
Enter the sources directory:
 
Enter the sources directory:
 
  % cd fpc
 
  % 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
  
 
== Supported targets ==
 
== Supported targets ==
Line 39: Line 58:
 
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.
 +
 
 +
=== WASI ===
  
On Ubuntu and MacOS, to build the compiler and FPC units for the WASI target:
+
==== Linux and MacOS ====
% 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):
+
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'':  
+
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.
 +
 +
==== 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''.
 +
  
 
[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.
Line 75: Line 111:
 
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.
 
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.
  
=== Embedded target ===
+
=== Embedded ===
  
 
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:
+
==== Linux and MacOS ====
  % make all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
+
 
 +
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, after building, install (using INSTALL_PREFIX to specify a destination within your home directory):
+
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
 
  % 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 ====
 +
 
 +
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.
  
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.
+
== 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 110: Line 160:
 
</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.
 +
 
 +
== 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'':

Revision as of 07:34, 2 April 2022

Instructions

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

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.

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

Supported targets

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.

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

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.


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 modern web browsers, although they require the web browser to provide the necessary WASI runtime services. See 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.

Embedded

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.

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.

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