emscripten icon indicating copy to clipboard operation
emscripten copied to clipboard

emcmake breaks CMAKE_PREFIX_PATH

Open henryiii opened this issue 2 years ago • 7 comments

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)

henryiii avatar Apr 25 '23 03:04 henryiii

I don't think this is intended behaviour. Do you have any idea how or why this might happen?

sbc100 avatar Apr 25 '23 04:04 sbc100

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.

henryiii avatar Apr 25 '23 15:04 henryiii

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.

henryiii avatar Apr 25 '23 15:04 henryiii

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.

henryiii avatar Apr 26 '23 02:04 henryiii

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.

jspanchu avatar Apr 12 '24 11:04 jspanchu

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.

mathstuf avatar Apr 12 '24 17:04 mathstuf

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:

  1. Set VTK_DIR environment var
  2. Set VTK_ROOT environment var
  3. Pass directory of vtk-config.cmake to CMAKE_PREFIX_PATH as an environment variable.
  4. 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.

jspanchu avatar Apr 12 '24 18:04 jspanchu