Difference between revisions of "WebAssembly/Compiler"

From Lazarus wiki
Jump to navigationJump to search
(→‎Prerequisites: - the external assembler is no longer required)
m (Fixed macOS capitalisation throughout)
 
(22 intermediate revisions by 3 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 ''wasm-ld'' linker. This the linker from the LLVM project. The external assembler ''llvm-mc'' is optional, since commit bc76487b878e59133ce3c2cc19ebb13f9a9826ea.
+
== Fedora ==
  
LLVM 11.0 is known to work. Development was done, using the Fedora packages llvm-11.0.0-1.fc33.x86_64 and lld-11.0.0-1.fc33.x86_64. 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).
+
Development was done, using the Fedora packages llvm-11.0.0-1.fc33.x86_64 and lld-11.0.0-1.fc33.x86_64.
  
=== Obtaining the compiler sources ===
+
== Ubuntu ==
  
The WebAssembly target was merged into FPC SVN trunk in r48955 on 2021-03-14. Since then, Free Pascal has moved to GitLab.
+
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
  
Get the sources:
+
Note: This assumes you have a $HOME/bin directory and it is in PATH.
  
git clone https://gitlab.com/freepascal.org/fpc/source.git fpc-wasm
+
== macOS ==
  
enter the directory:
+
=== Catalina ===
  cd fpc-wasm
+
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
 +
% 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
  
=== Supported targets ===
+
Note: This assumes you have a $HOME/bin directory and it is in PATH.
  
==== WASI - The WebAssembly System Interface ====
+
=== 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
  
[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. See the WASI website for more information.
+
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.
  
To build the compiler for the WASI target:
+
== Windows 10 ==
  
make all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
+
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
  
The following units have been ported for the WASI target:
+
Add C:\llvm\bin to your PATH.
  
* system
+
= Obtaining the compiler sources =
* 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:
+
== Linux and macOS ==
  
* dos
+
The WebAssembly compiler target is part of the 'main' branch of the GitLab FPC source repo. Get the source:
* sysutils
+
% git clone https://gitlab.com/freepascal.org/fpc/source.git fpc
* classes
 
* math
 
* fgl
 
  
See [[WebAssembly/Roadmap]] for details.
+
Enter the sources directory:
 +
% cd fpc
  
Compiled WASI binaries work with wasmtime version 0.23.0 or in the browser by opening:
+
== Windows ==
  
  https://webassembly.sh/
+
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
  
and drag and dropping the .wasm binary directly into the browser window.
+
Enter the sources directory:
 +
C:\Users\OnlyMe> cd fpc
  
==== Embedded target ====
+
= Building and installing =
  
The [[TARGET_Embedded|Embedded target]] is primarily used for embedded systems, 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.
+
If you are new to building the compiler, see [[Installing the Free Pascal Compiler]] and [[Cross compiling]].
  
make all OS_TARGET=embedded CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
+
FPC supports two WebAssembly compilation targets: WASI and embedded.
  
=== Using the compiler ===
+
== Compilation target: WASI ==
  
Hint: If your fpc.cfg has
+
=== Linux and macOS ===
<pre>
+
 
#IFDEF FPC_CROSSCOMPILING
+
Build the compiler and FPC units for the WASI target:
#IFDEF NEEDCROSSBINUTILS
+
% make clean all OS_TARGET=wasi CPU_TARGET=wasm32 BINUTILSPREFIX= OPT="-O-" PP=fpc
  -XP$FPCTARGET-
+
 
#ENDIF
+
Then, install, using INSTALL_PREFIX to specify a destination within your home directory:
#ENDIF
+
% make crossinstall OS_TARGET=wasi CPU_TARGET=wasm32 INSTALL_PREFIX=$HOME/fpcwasm
</pre>
+
 
 +
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
  
Enclose it in '''#IFNDEF CPUWASM32''' :
+
Note: This assumes you have a $HOME/bin directory and it is in PATH.
<pre>
 
#IFDEF FPC_CROSSCOMPILING
 
#IFDEF NEEDCROSSBINUTILS
 
#ifndef cpuwasm32
 
  -XP$FPCTARGET-
 
#endif
 
#ENDIF
 
#ENDIF
 
</pre>
 
  
Otherwise, you have to create symlinks wasm32-wasi-llvm-mc to llvm-mc, and wasm32-wasi-wasm-ld to wasm-ld.
+
=== Windows ===
  
==outdated: wasm-demo==
+
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.
  
Note: this section is outdated.
+
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
  
Wasm-demo is a Pascal WebAssembly demo project, ported Google's C WebAssembly example (https://codelabs.developers.google.com/codelabs/web-assembly-intro)
+
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
  
You follow these steps in order to get the demo project working:
+
Add C:\fpcwasm\bin\x86_64-win64 to your PATH if you have not already done so.
  
1. Get the project sources: https://github.com/skalogryz/wasm-demo
+
= Using the compiler =
  
===Using in webassembly.studio===
+
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.
2. Run the wasm compiler against lyff.pas, but request the assembler file to be kept
 
  pp -a lyff.pas
 
Webassembly.studio accepts the assembler file and would compile it on the server side.
 
  
3. open up  https://webassembly.studio and select "Create empty Wat Project". The project will consist of:
+
For Ubuntu, add these lines:
:main.html
+
<pre>
:main.js
+
#ifdef cpuwasm32
:main.wat
+
-Fu/home/yourusername/fpcwasm/lib/fpc/$fpcversion/units/$fpctarget/*
All files of the project can be edited through the web interface.
+
-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
 +
</pre>
  
4. Copy and paste the contents of the following files:
+
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.  
: (compiled) lyff.wat to main.wat.
 
: wasm-demo\webassembly.studio\main.html to main.html
 
: wasm-demo\webassembly.studio\main.js to main.js
 
  
Note: every time you copy and paste, don't forget to press "SAVE" button (on the right side of the web interface)
+
= Using the compiler with Lazarus =
  
5. once all files are update, hit "Build and Run"
+
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==
+
=See Also=
 
*[[WebAssembly]]
 
*[[WebAssembly]]
 
[[Category:WebAssembly]]
 
[[Category:WebAssembly]]

Latest revision as of 12: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