Repository: pyodide/pyodide

Issue:
Numpy v1.26.4 build fails: Module "features" does not exist
@ryanking13 @mattip @seberg

v1.26.3 build succeeds

Failure for v1.26.4:

<details><summary>Details</summary>
<p>

```
The Meson build system
Version: 1.3.1
Source dir: /home/hood/Documents/programming/pyodide/packages/numpy/build/numpy-1.26.4
Build dir: /home/hood/Documents/programming/pyodide/packages/numpy/build/numpy-1.26.4/.mesonpy-c6ekdglk
Build type: cross build
Project name: NumPy
Project version: 1.26.4
Cross compiler sanity tests disabled via the cross file.
C compiler for the host machine: /tmp/tmpqfmd_k4r/cc (emscripten 3.1.52 "emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.52 (fa478400df3351f7153c0279bc638784d3d90334)")
C linker for the host machine: /tmp/tmpqfmd_k4r/cc ld.wasm 18.0.0
C++ compiler for the host machine: /tmp/tmpqfmd_k4r/c++ (emscripten 3.1.52 "emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.52 (fa478400df3351f7153c0279bc638784d3d90334)")
C++ linker for the host machine: /tmp/tmpqfmd_k4r/c++ ld.wasm 18.0.0
Cython compiler for the host machine: cython (cython 3.0.8)
C compiler for the build machine: ccache cc (gcc 9.4.0 "cc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0")
C linker for the build machine: cc ld.bfd 2.34
C++ compiler for the build machine: ccache c++ (gcc 9.4.0 "c++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0")
C++ linker for the build machine: c++ ld.bfd 2.34
Cython compiler for the build machine: cython (cython 3.0.8)
Build machine cpu family: x86_64
Build machine cpu: x86_64
Host machine cpu family: wasm32
Host machine cpu: wasm
Target machine cpu family: wasm32
Target machine cpu: wasm
Program python3 found: YES (/tmp/build-env-mr2vjazb/bin/python)
Found pkg-config: YES (/usr/bin/pkg-config) 0.29.1
Run-time dependency python found: YES 3.12
Has header "Python.h" with dependency python: YES 
Compiler for C supports arguments -fno-strict-aliasing: YES 

../meson_cpu/x86/meson.build:2:15: ERROR: Module "features" does not exist
```

</p>
</details> 






Discussion:
Seems like the most likely culprit is:
https://github.com/numpy/numpy/pull/25748
According to this issue, https://github.com/numpy/numpy/issues/24750, it seems like vendored meson is not picked up for some reason.
I have a culprit. Let me check it out.

Resolving patch:
diff --git a/pyodide-build/pyodide_build/pypabuild.py b/pyodide-build/pyodide_build/pypabuild.py
--- a/pyodide-build/pyodide_build/pypabuild.py
+++ b/pyodide-build/pyodide_build/pypabuild.py
@@ -40,6 +40,19 @@
     "patchelf",
 ]
 
+# corresponding env variables for symlinks
+SYMLINK_ENV_VARS = {
+    "cc": "CC",
+    "c++": "CXX",
+    "ld": "LD",
+    "lld": "LLD",
+    "ar": "AR",
+    "gcc": "GCC",
+    "ranlib": "RANLIB",
+    "strip": "STRIP",
+    "gfortran": "FC",  # https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables
+}
+
 
 def _gen_runner(
     cross_build_env: Mapping[str, str],
@@ -207,13 +220,8 @@ def make_command_wrapper_symlinks(symlink_dir: Path) -> dict[str, str]:
             symlink_path.unlink()
 
         symlink_path.symlink_to(pywasmcross_exe)
-        if symlink == "c++":
-            var = "CXX"
-        elif symlink == "gfortran":
-            var = "FC"  # https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables
-        else:
-            var = symlink.upper()
-        env[var] = str(symlink_path)
+        if symlink in SYMLINK_ENV_VARS:
+            env[SYMLINK_ENV_VARS[symlink]] = str(symlink_path)
 
     return env
 


Test patch:
diff --git a/pyodide-build/pyodide_build/tests/test_pypabuild.py b/pyodide-build/pyodide_build/tests/test_pypabuild.py
--- a/pyodide-build/pyodide_build/tests/test_pypabuild.py
+++ b/pyodide-build/pyodide_build/tests/test_pypabuild.py
@@ -41,12 +41,13 @@ def test_make_command_wrapper_symlinks(tmp_path):
     assert not wrapper.is_symlink()
     assert wrapper.stat().st_mode & 0o755 == 0o755
 
-    for _, path in env.items():
+    for key, path in env.items():
         symlink_path = symlink_dir / path
 
         assert symlink_path.exists()
         assert symlink_path.is_symlink()
         assert symlink_path.name in pywasmcross.SYMLINKS
+        assert key in pypabuild.SYMLINK_ENV_VARS.values()
 
 
 def test_get_build_env(tmp_path):