Skip to content

Emscripten toolchain should point to cache sys root #133

@pezcode

Description

@pezcode

I mentioned this on gitter a while back but these things tend to disappear in the mist of time, so here's a trackable issue 🍉

Corrade's Emscripten toolchain file sets CMAKE_FIND_ROOT_PATH to upstream/emscripten/system. In contrast, Emscripten's own toolchain file sets it to the cache sys root (defaults to upstream/emscripten/cache/sysroot but is configurable). The latter contains generated headers like version.h added in 3.1.4 and included directly by emscripten.h.

This breaks when you link to a library whose include path is the root include directory (like EGL) and then directly include emscripten.h. In that case, the Corrade CMAKE_FIND_ROOT_PATH has priority over the compiler's default include path, and while emscripten.h is found there, compilation fails because it now can't find version.h.

Repro: add #include <emscripten.h> to TextureGLTest.cpp on Emscripten 3.1.4 and up.

There's a rather lengthy gitter thread with more detail here.

Edit: forgot to add the patch we've been using, been working fine so far:

diff --git a/generic/Emscripten-wasm.cmake b/generic/Emscripten-wasm.cmake
index 7b6865dcee27b73cea9e2849231f5f24bb541a79..aac9d9c2c22956efd861ceb769ede19d452508f4 100644
--- a/generic/Emscripten-wasm.cmake
+++ b/generic/Emscripten-wasm.cmake
@@ -40,8 +40,6 @@ if(NOT EMSCRIPTEN_PREFIX)
     endif()
 endif()
 
-set(EMSCRIPTEN_TOOLCHAIN_PATH "${EMSCRIPTEN_PREFIX}/system")
-
 if(CMAKE_HOST_WIN32)
     set(EMCC_SUFFIX ".bat")
 else()
@@ -58,8 +56,24 @@ set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_PREFIX}/em++${EMCC_SUFFIX}")
 set(CMAKE_AR "${EMSCRIPTEN_PREFIX}/emar${EMCC_SUFFIX}" CACHE PATH "Path to Emscripten ar")
 set(CMAKE_RANLIB "${EMSCRIPTEN_PREFIX}/emranlib${EMCC_SUFFIX}" CACHE PATH "Path to Emscripten ranlib")
 
+# The root path should point to the cache sysroot instead of
+# ${EMSCRIPTEN_PREFIX}/system. Otherwise, find modules may end up finding
+# include dirs in ${EMSCRIPTEN_PREFIX}/system, which is missing some generated
+# headers (e.g. version.h since 3.1.4). For example, FindEGL finds and sets the
+# root path as its include dir, and anything that links to it and includes
+# emscripten.h will fail to compile, because emscripten.h can't find version.h.
+# Taken from https://github.com/emscripten-core/emscripten/blob/74d6a15644e7f6e76ed6a1da9c6937b5cb7aef6e/cmake/Modules/Platform/Emscripten.cmake#L223
+execute_process(COMMAND "${EMSCRIPTEN_PREFIX}/em-config${EMCC_SUFFIX}" "CACHE"
+  RESULT_VARIABLE _emcache_result
+  OUTPUT_VARIABLE _emcache_output
+  OUTPUT_STRIP_TRAILING_WHITESPACE)
+if (NOT _emcache_result EQUAL 0)
+  message(FATAL_ERROR "Failed to find emscripten cache directory with command \"'${EMSCRIPTEN_PREFIX}/em-config${EMCC_SUFFIX}' CACHE\"! Process returned with error code ${_emcache_result}.")
+endif()
+set(EMSCRIPTEN_SYSROOT "${_emcache_output}/sysroot")
+
 set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH}
-    "${EMSCRIPTEN_TOOLCHAIN_PATH}"
+    "${EMSCRIPTEN_SYSROOT}"
     "${EMSCRIPTEN_PREFIX}")
 
 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions