Skip to content

fix: set CFLAGS to disable bulk-memory for wasm32 C deps#409

Open
r-near wants to merge 8 commits intomainfrom
fix/cflags-mcpu-mvp
Open

fix: set CFLAGS to disable bulk-memory for wasm32 C deps#409
r-near wants to merge 8 commits intomainfrom
fix/cflags-mcpu-mvp

Conversation

@r-near
Copy link
Copy Markdown
Contributor

@r-near r-near commented Mar 23, 2026

Summary

  • Set CFLAGS_wasm32_unknown_unknown="-mno-bulk-memory -mno-bulk-memory-opt" (and CXXFLAGS) in the build environment to prevent C/C++ dependencies from emitting bulk-memory wasm instructions

Problem

LLVM 21+ enables bulk-memory and bulk-memory-opt by default for wasm32-unknown-unknown. This causes C dependencies (e.g., the ring crate) to emit memory.fill/memory.copy instructions, which NEAR's VM rejects with CompilationError(PrepareError(Deserialization)).

Both flags are needed: LLVM 21 split bulk-memory into two separate features, and -mno-bulk-memory alone only disables the first — memory.fill still gets emitted through bulk-memory-opt. See llvm/llvm-project#109443 for related discussion.

Other post-MVP features (sign-ext, mutable-globals) are left enabled as NearVM supports them since protocol 62.

Testing

Verified with the register-contract from defuse-protocol/near-outlayer which depends on ring (C crypto code):

Scenario Result
clang 18 + this fix Builds and deploys, identical output to without fix
clang 21 + this fix Builds and deploys successfully
clang 21 without fix Fails at wasm-opt with memory.fill errors

Fixes #408

… bulk-memory

LLVM 21+ enables `bulk-memory` and `bulk-memory-opt` by default for
wasm32-unknown-unknown, causing C dependencies (e.g., the `ring` crate)
to emit `memory.fill`/`memory.copy` instructions. NEAR's VM rejects
these with `CompilationError(PrepareError(Deserialization))`.

The `-mno-bulk-memory` flag is insufficient because LLVM 21 introduced
a separate `bulk-memory-opt` feature that is not disabled by it.
`-mcpu=mvp` restricts the C compiler to the MVP instruction set,
which is future-proof against further feature splits.

Fixes #408
Copilot AI review requested due to automatic review settings March 23, 2026 19:21
@r-near r-near requested a review from a team as a code owner March 23, 2026 19:21
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates cargo-near-build’s contract build environment to force C/C++ dependencies compiled during cargo near build to target the WebAssembly MVP instruction set, preventing NEAR-incompatible bulk-memory instructions from being emitted by newer LLVM toolchains.

Changes:

  • Set CFLAGS="-mcpu=mvp" and CXXFLAGS="-mcpu=mvp" for the wasm build invocation.
  • Add env_keys constants for CFLAGS and CXXFLAGS.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
cargo-near-build/src/near/build/mod.rs Adds default C/C++ compiler flags to the cargo build environment to restrict emitted wasm instructions to MVP.
cargo-near-build/src/env_keys.rs Introduces env var key constants for CFLAGS and CXXFLAGS.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cargo-near-build/src/near/build/mod.rs Outdated
Comment on lines +223 to +224
(env_keys::CFLAGS_ENV, "-mcpu=mvp"),
(env_keys::CXXFLAGS_ENV, "-mcpu=mvp"),
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

Setting CFLAGS/CXXFLAGS here will override any flags the user already has in their shell environment for the entire cargo build invocation (not just wasm-target C/C++ compilation). This can break builds that rely on additional CFLAGS or that compile any host-side C code during the build. Consider (a) appending -mcpu=mvp to any existing CFLAGS/CXXFLAGS values instead of replacing them, and/or (b) scoping the flags to the wasm32 target only (so host compilation isn’t affected) while still allowing --env to fully override when needed.

Suggested change
(env_keys::CFLAGS_ENV, "-mcpu=mvp"),
(env_keys::CXXFLAGS_ENV, "-mcpu=mvp"),
("CFLAGS_wasm32-unknown-unknown", "-mcpu=mvp"),
("CXXFLAGS_wasm32-unknown-unknown", "-mcpu=mvp"),

Copilot uses AI. Check for mistakes.
@frol
Copy link
Copy Markdown
Contributor

frol commented Mar 23, 2026

This sounds like a risky and just a coincidental remedy rather a proper fix. This may break reproducible builds verification, so be careful with it.

Use CFLAGS_wasm32_unknown_unknown instead of CFLAGS to avoid affecting
host-side C compilation. The cc crate checks target-scoped env vars
before the generic CFLAGS, so this only affects wasm32 cross-compilation.
@r-near
Copy link
Copy Markdown
Contributor Author

r-near commented Mar 23, 2026

That's a fair concern. On the reproducibility side though, I verified that for LLVM 18 (where builds already work), the output is bit-for-bit identical with and without the flag — so this shouldn't change anything for existing setups. For LLVM 21, builds fail entirely without it, so there's no existing reproducibility to break. The flags are also scoped to CFLAGS_wasm32_unknown_unknown so host-side C compilation is unaffected.

Happy to hear if you see a better approach though — the core problem is that newer LLVM versions emit bulk-memory instructions from C deps by default, and cargo-near doesn't have a way to prevent that today.

r-near added 2 commits March 24, 2026 16:39
Use -mno-bulk-memory -mno-bulk-memory-opt instead of -mcpu=mvp to only
disable bulk-memory instructions while keeping other post-MVP features
(sign-ext, mutable-globals) that NearVM supports since protocol 62.
@r-near r-near changed the title fix: set CFLAGS/CXXFLAGS to -mcpu=mvp to prevent C deps from emitting bulk-memory fix: set CFLAGS to disable bulk-memory for wasm32 C deps Mar 24, 2026
r-near and others added 4 commits March 24, 2026 16:49
Edition 2024 implies resolver 3 by default, so no need for an
explicit resolver field. Aligns templates with the main project
and new-project template which already use edition 2024.
@r-near r-near closed this Apr 1, 2026
@r-near r-near reopened this Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] cargo-near should use -C target-cpu=mvp and wasm-opt --signext-lowering to produce mvp compatible wasm

4 participants