Repository: pyodide/pyodide

Issue:
On first call, `pyodide config get emscripten_version` returns `Downloading xbuild environment Installing xbuild environment 3.1.27` instead of `3.1.27`
## 🐛 Bug

In [the docs for out-of-tree builds](https://pyodide.org/en/stable/development/building-and-testing-packages.html#building-and-testing-packages-out-of-tree) it gives this code snippet:

```bash
pip install pyodide-build

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk

PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
source emsdk_env.sh
```
But this doesn't work because on the first call, `pyodide config get emscripten_version` outputs this:
```
Downloading xbuild environment
Installing xbuild environment
3.1.27
```
On subsequent calls it returns `3.1.27`.

### To Reproduce

See above.

### Expected behavior

Calls to `pyodide config get emscripten_version` should only ever output the version string such that this command can be reliably used in build automation.

### Environment

- Pyodide Version<!-- (e.g. 1.8.1) -->: Pyodide CLI Version: 0.2.2

### Additional context

As a workaround for build scripts, `pyodide config get emscripten_version` can be called once before actually using it.



Discussion:
Thanks for the report @josephrocca! I guess we need to be more careful when printing log messages to stdout...
Is this now fixed by https://github.com/pyodide/pyodide/pull/3442?
No, it is not fixed yet. Probably I'll make a fix in a few days, but I got COVID-19 so I'm not in a very good condition to code :<
Hope you feel better soon @ryanking13!
This might be a slightly personal question @ryanking13, but are you doing OK? I hope you have a support network with you. Sending fast-recovery thoughts your way!
@agoose77 Yeah, I am totally okay, thanks for asking! I am just experiencing some typical omicron symptoms, but it is getting better quickly.

Resolving patch:
diff --git a/pyodide-build/pyodide_build/cli/config.py b/pyodide-build/pyodide_build/cli/config.py
--- a/pyodide-build/pyodide_build/cli/config.py
+++ b/pyodide-build/pyodide_build/cli/config.py
@@ -19,7 +19,7 @@ def callback() -> None:
 
 
 def _get_configs() -> dict[str, str]:
-    initialize_pyodide_root()
+    initialize_pyodide_root(quiet=True)
 
     configs: dict[str, str] = get_make_environment_vars()
 
diff --git a/pyodide-build/pyodide_build/out_of_tree/utils.py b/pyodide-build/pyodide_build/out_of_tree/utils.py
--- a/pyodide-build/pyodide_build/out_of_tree/utils.py
+++ b/pyodide-build/pyodide_build/out_of_tree/utils.py
@@ -1,10 +1,12 @@
 import os
+from contextlib import ExitStack, redirect_stdout
+from io import StringIO
 from pathlib import Path
 
 from ..common import search_pyodide_root
 
 
-def ensure_env_installed(env: Path) -> None:
+def ensure_env_installed(env: Path, *, quiet: bool = False) -> None:
     if env.exists():
         return
     from .. import __version__
@@ -15,11 +17,16 @@ def ensure_env_installed(env: Path) -> None:
             "To use out of tree builds with development Pyodide, you must explicitly set PYODIDE_ROOT"
         )
 
-    download_xbuildenv(__version__, env)
-    install_xbuildenv(__version__, env)
+    with ExitStack() as stack:
+        if quiet:
+            # Prevent writes to stdout
+            stack.enter_context(redirect_stdout(StringIO()))
 
+        download_xbuildenv(__version__, env)
+        install_xbuildenv(__version__, env)
 
-def initialize_pyodide_root() -> None:
+
+def initialize_pyodide_root(*, quiet: bool = False) -> None:
     if "PYODIDE_ROOT" in os.environ:
         return
     try:
@@ -29,4 +36,4 @@ def initialize_pyodide_root() -> None:
         pass
     env = Path(".pyodide-xbuildenv")
     os.environ["PYODIDE_ROOT"] = str(env / "xbuildenv/pyodide-root")
-    ensure_env_installed(env)
+    ensure_env_installed(env, quiet=quiet)


Test patch: