emscripten
emscripten copied to clipboard
emcmake breaks CMAKE_PREFIX_PATH
If I use emcmake, CMAKE_PREFIX_PATH breaks. For example, the following CMake file:
cmake_minimum_required(VERSION 3.15...3.26)
project(CMCheck LANGUAGES CXX)
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pre")
find_package(CheckMe CONFIG REQUIRED)
And the following file in pre/CheckMeConfig.cmake:
message(STATUS "Found correctly")
Produces the expected message if run on the host CMake, but when run through emcmake, it produces:
$ emcmake cmake -S . -B build
configure: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR=/emsdk/node/15.14.0_64bit/bin/node;--experimental-wasm-bulk-memory;--experimental-wasm-threads
CMake Error at CMakeLists.txt:7 (find_package):
Could not find a package configuration file provided by "CheckMe" with any
of the following names:
CheckMeConfig.cmake
checkme-config.cmake
Add the installation prefix of "CheckMe" to CMAKE_PREFIX_PATH or set
"CheckMe_DIR" to a directory containing one of the above files. If
"CheckMe" provides a separate development package or SDK, be sure it has
been installed.
-- Configuring incomplete, errors occurred
Is this expected? A bug with CMake I should report there, like faulty platform logic? Setting CheckMe_DIR works.
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.32 (eab98adf462c39f3c31d348331c4830bcaa36949)
clang version 17.0.0 (https://github.com/llvm/llvm-project df82394e7a2d06506718cafa347bf7827c79fc4f)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin
CMAKE_FIND_USE_CMAKE_PATH and CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH are not set to false.
(This is breaking the CMake based Python build backends scikit-build-core in Pyodide, which discovers the header only pybind11 via this method, FYI)
I don't think this is intended behaviour. Do you have any idea how or why this might happen?
I was hoping you might. :) I've been doing a binary search through the cross-compiling file (https://github.com/emscripten-core/emscripten/blob/main/cmake/Modules/Platform/Emscripten.cmake) and seeing what I have to disable to make this work. I can make it work with the following two places both commented out (but not separately):
https://github.com/emscripten-core/emscripten/blob/cb5ca6e54161f8baa95c634d80fe4e9347166eed/cmake/Modules/Platform/Emscripten.cmake#L81
https://github.com/emscripten-core/emscripten/blob/cb5ca6e54161f8baa95c634d80fe4e9347166eed/cmake/Modules/Platform/Emscripten.cmake#L245-L247
I have no idea why the first one needs to be commented. The second one doesn't seem like it should affect the PREFIX_PATH search given its description, and when used directly without the toolchain file, it doesn't seem to. I'm wondering if multiple settings are conflicting and exposing a bug in CMake, or if there's some setting somewhere else I'm not aware of. Really don't know why that first line affects anything.
I can reproduce this in pure CMake:
cmake_minimum_required(VERSION 3.15...3.26)
project(CMCheck LANGUAGES CXX)
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pre")
list(APPEND CMAKE_FIND_ROOT_PATH "/emsdk/upstream/emscripten")
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
find_package(CheckMe CONFIG REQUIRED)
Setting both of these causes CMAKE_PREFIX_PATH to be ignored. Removing CMAKE_FIND_ROOT_PATH in the toolchain file isn't enough, for some reason, though.
There's also a possible workaround: set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) does seem to fix the issue. From reading the docs, I still think this is confusing - to me it seems like this variable is supposed to control the system paths, not specific paths specified via CMAKE_PREFIX_PATH.
I'm working around this for now in https://github.com/scikit-build/scikit-build-core/pull/303. Not extremely happy with the workaround, so still would like to work out if this the expected behavior from CMake.
Emscripten.cmake should set CMAKE_FIND_ROOT_PATH_MODE_PACKAGE to BOTH here. Wdyt @mathstuf?
Otherwise, the only way to get packages found using emcmake is by passing -DPackageName_DIR=/path/to/where/PackageName-config.cmake/lives.
Maybe? This is something best investigated with a proper SDK setup to see how it behaves under different settings. ONLY certainly seems wrong though if CMAKE_PREFIX_PATH stops working as intended.
The only approach that worked is passing VTK_DIR as a CMake arg in https://github.com/Kitware/vtkWasmBenchmarks/blob/main/build.sh#L23. note that, here the path points to an SDK install tree, not a build tree.
I've tried all these to no effect:
- Set VTK_DIR environment var
- Set VTK_ROOT environment var
- Pass directory of
vtk-config.cmaketo CMAKE_PREFIX_PATH as an environment variable. - Same as above but pass it as a command line variable.
Interestingly, passing -DVTK_DIR=/../.. as a cmake argument is the only approach that works. Besides using BOTH in the project CMakeLists.txt as mentioned here ofcourse.