Skip to content

feat: support building for WASI - #1314

Open
msuozzo wants to merge 1 commit into
rust-lang:mainfrom
msuozzo:push-knnuksvulkut
Open

msuozzo wants to merge 1 commit into
rust-lang:mainfrom
msuozzo:push-knnuksvulkut

Conversation

@msuozzo

@msuozzo msuozzo commented Oct 11, 2026 •

Copy link
Copy Markdown

Build the vendored libgit2 for target_os = "wasi" (tested on
wasm32-wasip1; wasip2 is untested). There is no system libgit2 to link
against, so WASI always builds the vendored copy. In git2, path
conversions accept WASI's OsStr, and Repository::open_ext and
discover_path join ceiling directories themselves, since std's
env::join_paths is unsupported on WASI.

WASI preview 1 lacks several things libgit2's unix build assumes:

  • mmap: build with NO_MMAP, so pack windows are read into memory.
  • threads: leave GIT_THREADS undefined, and reject the -threads
    targets, where git2's Send types could then race inside libgit2.
  • network connections: replace streams/socket.c with a stream that
    always fails, and reject the https and ssh features.
  • user and process identity: wasi/compat.c defines getuid and friends
    (uid 0, pid 1). wasi-libc has no pwd.h, so wasi/include/pwd.h
    provides one; libgit2 only consults it when setuid, so the home
    directory comes from $HOME.

On wasm32, size_t is unsigned long but SIZE_MAX == UINT_MAX, so
libgit2's integer.h passes a size_t * to __builtin_uadd_overflow.
The types have the same width, so clang's error is downgraded for WASI
as a stopgap until libgit2 uses the type-generic builtins
(libgit2/libgit2#7406).

libz-sys before 1.1.30 builds zlib for WASI without default allocators
(rust-lang/libz-sys#273), so every object read fails. Require 1.1.30.

Add a CI job that builds for wasm32-wasip1 with wasi-sdk and runs the
tests under wasmtime. MSRV only builds: before Rust 1.94, std on WASI
can't canonicalize paths and its remove_dir_all fails on what the
tests create. For the tests:

  • std has no temporary directory on WASI, so tests create theirs with
    test::tempdir(), which points tempfile at /tmp there, as tempfile's
    own tests do. The runner preopens /tmp.
  • Test helpers with only unix and windows variants (realpath,
    ostr_to_cstr, file URLs, the symlink in repo_status) now cover
    WASI, and search_path joins paths itself.
  • Skipped on WASI: compile_fail (trybuild runs cargo),
    non_utf8_branch (WASI paths are UTF-8), and two tests that remove
    directories through paths ending in a slash, which wasmtime rejects
    (wasip1 path_remove_directory fails with paths with trailing slashes bytecodealliance/wasmtime#11524).

@rustbot rustbot added the S-waiting-on-review Status: Waiting on review label Oct 11, 2026

@DanielEScherzer DanielEScherzer left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not going to pretend like I understand everything here, but some suggestions

View changes since this review

Comment thread .github/workflows/main.yml Outdated
Comment thread libgit2-sys/wasi/compat.c

pid_t getpgid(pid_t pid)
{
GIT_UNUSED(pid);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure we should be reusing the GIT_UNUSED macro, maybe just void cast like the pwd stub?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GIT_UNUSED is already used elsewhere in the file as compat.c is built as part of libgit2 + depends on its internal headers anyway and so it follows libgit2's conventions. pwd.h is a libc stand-in, so it can't assume those headers, hence the difference.

@msuozzo

msuozzo commented Oct 11, 2026

Copy link
Copy Markdown
Author

I intend to incorporate the changes from #1316, which run the test suite on WASI, once libz-sys releases the fix they need (rust-lang/libz-sys#276).

Build the vendored libgit2 for `target_os = "wasi"` (tested on
wasm32-wasip1; wasip2 is untested). There is no system libgit2 to link
against, so WASI always builds the vendored copy. In git2, path
conversions accept WASI's `OsStr`, and `Repository::open_ext` and
`discover_path` join ceiling directories themselves, since std's
`env::join_paths` is unsupported on WASI.

WASI preview 1 lacks several things libgit2's unix build assumes:

- mmap: build with `NO_MMAP`, so pack windows are read into memory.
- threads: leave `GIT_THREADS` undefined, and reject the -threads
  targets, where git2's `Send` types could then race inside libgit2.
- network connections: replace `streams/socket.c` with a stream that
  always fails, and reject the `https` and `ssh` features.
- user and process identity: wasi/compat.c defines getuid and friends
  (uid 0, pid 1). wasi-libc has no pwd.h, so wasi/include/pwd.h
  provides one; libgit2 only consults it when setuid, so the home
  directory comes from $HOME.

On wasm32, `size_t` is `unsigned long` but `SIZE_MAX == UINT_MAX`, so
libgit2's `integer.h` passes a `size_t *` to `__builtin_uadd_overflow`.
The types have the same width, so clang's error is downgraded for WASI
as a stopgap until libgit2 uses the type-generic builtins
(libgit2/libgit2#7406).

libz-sys before 1.1.30 builds zlib for WASI without default allocators
(rust-lang/libz-sys#273), so every object read fails. Require 1.1.30.

Add a CI job that builds for wasm32-wasip1 with wasi-sdk and runs the
tests under wasmtime. MSRV only builds: before Rust 1.94, std on WASI
can't canonicalize paths and its remove_dir_all fails on what the
tests create. For the tests:

- std has no temporary directory on WASI, so tests create theirs with
  `test::tempdir()`, which points tempfile at /tmp there, as tempfile's
  own tests do. The runner preopens /tmp.
- Test helpers with only unix and windows variants (`realpath`,
  `ostr_to_cstr`, file URLs, the symlink in `repo_status`) now cover
  WASI, and `search_path` joins paths itself.
- Skipped on WASI: `compile_fail` (trybuild runs cargo),
  `non_utf8_branch` (WASI paths are UTF-8), and two tests that remove
  directories through paths ending in a slash, which wasmtime rejects
  (bytecodealliance/wasmtime#11524).
@msuozzo
msuozzo force-pushed the push-knnuksvulkut branch 2 times, most recently from 5d3f083 to c770a67 Compare October 12, 2026 16:25
@msuozzo

msuozzo commented Oct 12, 2026

Copy link
Copy Markdown
Author

libz-sys 1.1.30 is out, so I've folded in #1316. libgit2-sys now requires 1.1.30, and the WASI job runs the test suite under wasmtime.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Waiting on review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants