Initial commit

This commit is contained in:
Michael Franzl 2024-05-02 17:38:17 +02:00
commit 68fbcfb32e
Signed by: michael
GPG key ID: F2FA572344C60B07
9 changed files with 361 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
result

43
README.md Normal file
View file

@ -0,0 +1,43 @@
# wasm-sdk
A SDK for LLVM C and C++ WebAssembly development based on Nix.
It builds all required dependencies (*clang, clang++, wasm-ld, libcxx, compiler-rt*, and *wasi-libc*)
and exposes the following environment variables needed to compile to WebAssembly, for example:
```
WASM_LLVM=/nix/store/akpcpb9ycb98jjbp6dyg1j65vkwqp1lm-wasm-llvm
WASM_LIBCXX_LIB=/nix/store/ll4hi2jkhv8399dhbz6q0qgw97c6hyja-wasm-libcxx/lib
WASM_LIBCXX_INC=/nix/store/ll4hi2jkhv8399dhbz6q0qgw97c6hyja-wasm-libcxx/include/c++/v1
WASM_COMPILER_RT_LIB=/nix/store/59lmk928vly8126zq7mabzc9123hknj2-wasm-compiler-rt/lib/wasi
WASI_LIBC_LIB=/nix/store/qislis4ivwv3l721dbhghax6j4kp3ccb-wasi-libc/lib
WASI_LIBC_INC=/nix/store/71k5vk20275571n0bsij42qdasbxc82b-wasi-libc-dev/include
```
## Goals
* Lean toolchain leveraging as much as possible from upstream sources.
* Basic levels of WASI (no threading, no exceptions).
## Versions
* LLVM: 17
* wasi-libc: 21
## Usage
The included derivation produces a single file with exportable environment variables.
Example:
```sh
env $(cat $(nix-build -E 'with import <nixpkgs> {}; callPackage ./default.nix {}')) printenv
```
A *flake* is also included that exposes the needed variables in the following ways (three ways to choose from, for convenience):
1. as the `paths` (*attrset* type) *passthru* of the *derivation* of the *default package* (to use in other *flakes*).
2. as exported environment variables in the *default development shell* (`nix develop`).
3. as text in a file (`nix build` produces the file `./result`).

34
default.nix Normal file
View file

@ -0,0 +1,34 @@
{ pkgs, lib, ... }:
let
wasm-llvm = import ./wasm-llvm.nix { inherit pkgs; };
wasm-libcxx = import ./wasm-libcxx.nix { inherit pkgs; };
wasi-libc = import ./wasi-libc.nix { inherit pkgs; };
wasm-compiler-rt = import ./wasm-compiler-rt.nix { inherit pkgs; };
paths = {
WASM_LLVM = wasm-llvm;
WASM_LIBCXX_LIB = "${wasm-libcxx}/lib";
WASM_LIBCXX_INC = "${wasm-libcxx}/include/c++/v1";
WASM_COMPILER_RT_LIB = "${wasm-compiler-rt}/lib/wasi";
WASI_LIBC_LIB = "${wasi-libc}/lib";
WASI_LIBC_INC = "${wasi-libc.dev}/include";
};
pathsFileContents = lib.strings.concatLines (
lib.attrsets.mapAttrsToList (name: value: name + "=" + value) paths
);
in
pkgs.stdenv.mkDerivation rec {
name = "wasm-sdk";
version = "1.0.0";
dontUnpack = true;
installPhase = ''
echo "${pathsFileContents}" > $out
'';
passthru = {
inherit paths;
};
}

27
flake.lock generated Normal file
View file

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1714253743,
"narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

17
flake.nix Normal file
View file

@ -0,0 +1,17 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs =
{ self, nixpkgs }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
package = import ./default.nix pkgs;
in
{
packages.x86_64-linux.default = package;
formatter.x86_64-linux = pkgs.nixfmt-rfc-style;
devShells.x86_64-linux.default = pkgs.mkShell package.paths;
};
}

32
wasi-libc.nix Normal file
View file

@ -0,0 +1,32 @@
{ pkgs }:
with pkgs;
stdenv.mkDerivation rec {
name = "wasi-libc";
version = "21";
src = fetchFromGitHub {
owner = "WebAssembly";
repo = "wasi-libc";
rev = "refs/tags/wasi-sdk-21";
hash = "sha256-mQp54JYb3bsmyQy5SByPFu9uxhKDy/XXF7lF9bEUfOo=";
};
wasm-llvm = import ./wasm-llvm.nix { inherit pkgs; };
outputs = [
"out"
"dev"
"share"
];
dontInstall = true;
dontFixup = true;
makeFlags = [
"CC=${wasm-llvm}/bin/clang"
"NM=${wasm-llvm}/bin/nm"
"AR=${wasm-llvm}/bin/ar"
"SYSROOT_LIB=${builtins.placeholder "out"}/lib"
"SYSROOT_INC=${builtins.placeholder "dev"}/include"
"SYSROOT_SHARE=${builtins.placeholder "share"}/share"
];
}

40
wasm-compiler-rt.nix Normal file
View file

@ -0,0 +1,40 @@
{ pkgs }:
with pkgs;
stdenv.mkDerivation rec {
name = "wasm-compiler-rt";
version = "17.0.6";
src = fetchzip {
url = "https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-17.0.6.tar.gz";
hash = "sha256-8MEDLLhocshmxoEBRSKlJ/GzJ8nfuzQ8qn0X/vLA+ag=";
};
wasm-llvm = import ./wasm-llvm.nix { inherit pkgs; };
nativeBuildInputs = [
cmake
ninja
];
dontFixup = true;
configurePhase = ''
cmake -G Ninja \
-DCMAKE_MODULE_PATH=${wasm-llvm.dev}/cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=${wasm-llvm.dev}/cmake/toolchain.cmake \
-DCOMPILER_RT_BAREMETAL_BUILD=ON \
-DCOMPILER_RT_INCLUDE_TESTS=OFF \
-DCOMPILER_RT_HAS_FPIC_FLAG=OFF \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
-DCMAKE_INSTALL_PREFIX=$out \
$src/compiler-rt/lib/builtins
'';
buildPhase = ''
ninja -v
'';
installPhase = ''
ninja -v install
'';
}

69
wasm-libcxx.nix Normal file
View file

@ -0,0 +1,69 @@
{ pkgs }:
with pkgs;
stdenv.mkDerivation rec {
name = "wasm-libcxx";
version = "17.0.6";
src = fetchzip {
url = "https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-17.0.6.tar.gz";
hash = "sha256-8MEDLLhocshmxoEBRSKlJ/GzJ8nfuzQ8qn0X/vLA+ag=";
};
wasm-llvm = import ./wasm-llvm.nix { inherit pkgs; };
wasi-libc = import ./wasi-libc.nix { inherit pkgs; };
dontFixup = true;
nativeBuildInputs = [
cmake
ninja
python3
];
configurePhase = ''
cmake -G Ninja \
-DCMAKE_C_COMPILER_WORKS=ON \
-DCMAKE_CXX_COMPILER_WORKS=ON \
-DCMAKE_AR=${wasm-llvm}/bin/ar \
-DCMAKE_MODULE_PATH=${wasm-llvm.dev}/cmake \
-DCMAKE_TOOLCHAIN_FILE=/${wasm-llvm.dev}/cmake/toolchain.cmake \
-DCMAKE_STAGING_PREFIX=$out \
-DCMAKE_POSITION_INDEPENDENT_CODE=OFF \
-DLIBCXX_ENABLE_THREADS:BOOL=OFF \
-DLIBCXX_HAS_PTHREAD_API:BOOL=OFF \
-DLIBCXX_HAS_EXTERNAL_THREAD_API:BOOL=OFF \
-DLIBCXX_HAS_WIN32_THREAD_API:BOOL=OFF \
-DLLVM_COMPILER_CHECKED=ON \
-DCMAKE_BUILD_TYPE=Release \
-DLIBCXX_ENABLE_SHARED:BOOL=OFF \
-DLIBCXX_ENABLE_EXCEPTIONS:BOOL=OFF \
-DLIBCXX_ENABLE_FILESYSTEM:BOOL=OFF \
-DLIBCXX_ENABLE_ABI_LINKER_SCRIPT:BOOL=OFF \
-DLIBCXX_CXX_ABI=libcxxabi \
-DLIBCXX_HAS_MUSL_LIBC:BOOL=ON \
-DLIBCXX_ABI_VERSION=2 \
-DLIBCXXABI_ENABLE_EXCEPTIONS:BOOL=OFF \
-DLIBCXXABI_ENABLE_SHARED:BOOL=OFF \
-DLIBCXXABI_SILENT_TERMINATE:BOOL=ON \
-DLIBCXXABI_ENABLE_THREADS:BOOL=OFF \
-DLIBCXXABI_HAS_PTHREAD_API:BOOL=OFF \
-DLIBCXXABI_HAS_EXTERNAL_THREAD_API:BOOL=OFF \
-DLIBCXXABI_HAS_WIN32_THREAD_API:BOOL=OFF \
-DLIBCXXABI_USE_LLVM_UNWINDER:BOOL=OFF \
-DUNIX:BOOL=ON \
--debug-trycompile \
-DCMAKE_SYSROOT_COMPILE=${wasi-libc.dev} \
-DCMAKE_SYSROOT_LINK=${wasi-libc} \
-DCMAKE_CXX_FLAGS="-fno-exceptions" \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
${src}/runtimes
'';
buildPhase = ''
ninja -v
'';
installPhase = ''
ninja -v install
'';
}

98
wasm-llvm.nix Normal file
View file

@ -0,0 +1,98 @@
{ pkgs }:
with pkgs;
stdenv.mkDerivation {
name = "wasm-llvm";
version = "17.0.6";
src = fetchzip {
url = "https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-17.0.6.tar.gz";
hash = "sha256-8MEDLLhocshmxoEBRSKlJ/GzJ8nfuzQ8qn0X/vLA+ag=";
};
nativeBuildInputs = [
cmake
ninja
python3
];
phases = [
"configurePhase"
"installPhase"
];
outputs = [
"out"
"dev"
];
configurePhase = ''
cmake -G Ninja \
-DCMAKE_INSTALL_PREFIX=$out \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ZLIB=OFF \
-DLLVM_ENABLE_TERMINFO=OFF \
-DLLVM_ENABLE_ZSTD=OFF \
-DLLVM_STATIC_LINK_CXX_STDLIB=ON \
-DLLVM_HAVE_LIBXAR=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_UTILS=OFF \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_TARGETS_TO_BUILD=WebAssembly \
-DLLVM_DEFAULT_TARGET_TRIPLE=wasm32-wasi \
-DLLVM_ENABLE_PROJECTS="lld;clang;clang-tools-extra" \
-DLLVM_INSTALL_BINUTILS_SYMLINKS=TRUE \
-DLLVM_ENABLE_LIBXML2=OFF \
$src/llvm
'';
installPhase = ''
mkdir -p $dev/cmake
cat > $dev/cmake/toolchain.cmake <<-CMAKE
set(CMAKE_SYSTEM_NAME WASI)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR wasm32)
set(triple wasm32-wasi)
set(CMAKE_C_COMPILER $out/bin/clang)
set(CMAKE_CXX_COMPILER $out/bin/clang++)
set(CMAKE_ASM_COMPILER $out/bin/clang)
set(CMAKE_AR $out/bin/llvm-ar)
set(CMAKE_RANLIB $out/bin/llvm-ranlib)
set(CMAKE_C_COMPILER_TARGET wasm32-wasi)
set(CMAKE_CXX_COMPILER_TARGET wasm32-wasi)
set(CMAKE_ASM_COMPILER_TARGET wasm32-wasi)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
CMAKE
mkdir -p $dev/cmake/Platform
echo "set(WASI 1)" > $dev/cmake/Platform/WASI.cmake
ninja -v \
install-clang \
install-clang-format \
install-clang-tidy \
install-clang-apply-replacements \
install-lld \
install-llvm-mc \
install-llvm-ranlib \
install-llvm-strip \
install-llvm-dwarfdump \
install-clang-resource-headers \
install-ar \
install-ranlib \
install-strip \
install-nm \
install-size \
install-strings \
install-objdump \
install-objcopy \
install-c++filt \
install-llvm-config
'';
}