CMAKE_PREFIX_PATH does not work as expected

I’m compiling the same Qt/QML application on Windows, Linux, MacOS, WebAssembly, iOS, and Android. So far, I found that detection of Qt’s components only works on Windows, regardless whether I’m using it to compile a Windows version or cross-compiling to Android. It doesn’t work neither on MacOS nor on Linux.

I tried pointing CMAKE_PREFIX_PATH to Qt’s installation prefix (~/Qt/5.15.0/wasm_32/), but it keeps on complaining about QtConfig.cmake. The only alternative I found to work was passing -DQt5_DIR for QtConfig.cmake to be found, but then it would keep on asking for at least 10 more .cmake files which I need to pass their paths one by one using _DIR variables. This way I would always end with a huge command and it’s a major source of annoyance.

Note that I do not want to install Qt using apt or any other package manager. I only want to use Qt’s installer since it gives me the flexibility of having multiple versions targeting multiple frameworks.

Is it a problem in Qt? CMake? Ubuntu?

Qt: 5.15.0

CMake: 3.18.0

Ubuntu: 20.04

this is likely not a problem with Qt, CMake or Ubuntu. Prefix path is working just fine for me on Ubuntu.

Maybe you are not providing the correct path. Can you post the folder structure for the *.cmake file you want to be found in your build?

Yes, I’m pretty sure that I’m pointing to the correct path. Here is the folder structure:
tree -d ~/Qt/5.15.0/wasm_32/
/home/[user]/Qt/5.15.0/wasm_32/
├── bin
├── doc
│ .
│ .
│ .
├── include
│ ├── QtAccessibilitySupport
│ │ └── 5.15.0
│ │ └── QtAccessibilitySupport
│ │ └── private
│ ├── QtBodymovin
│ │ └── 5.15.0
│ │ └── QtBodymovin
│ │ └── private
│ .
│ .
│ .
├── lib
│ ├── cmake
│ ├── Qt5
│ │ ├── Qt5Config.cmake
│ │ ├── Qt5ConfigVersion.cmake
│ │ └── Qt5ModuleLocation.cmake
│ ├── Qt5AccessibilitySupport
│ │ ├── Qt5AccessibilitySupportConfig.cmake
│ │ └── Qt5AccessibilitySupportConfigVersion.cmake
│ │ .
│ │ .
│ │ .
├── mkspecs
│ .
│ .
│ .
├── qml
│ .
│ .
│ .
└── translations

Please post the command line you are using to set CMAKE_PREFIX_PATH and show the find_package() calls you are using to find Qt. Also show the exact output that demonstrates that Qt is not being found. Probably it will be easiest to diagnose this for Linux or MacOS, so please show for one of those two platforms.

I could solve the problem by adding this to the beginning of my CMake script:

list(APPEND CMAKE_PREFIX_PATH “~/Qt/5.15.0/wasm_32”)

Neither passing it as a command-line parameter nor as an env variable worked.
Is this expected?

EDIT: I was wrong

There seems to be more going on here than we can tell from the description so far. Please provide a complete example with steps that someone else can use to reproduce. Leaving out details will only slow down anyone’s chance to help.

I was wrong. I made the change then tried to run the configuration in a build folder that was already configured by passing all the library paths manually.

Now I’m sure that I found it:
The toolchains had this:
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

It doesn’t look like setting CMAKE_PREFIX_PATH was enough. I had to do this also:
list(APPEND CMAKE_FIND_ROOT_PATH “~/Qt/5.15.0/wasm_32”)

Using ~ in a CMake path isn’t going to help much. You should use $HOME (on the shell) or $ENV{HOME} (in CMake code) instead.

I believe that using ~ does actually work in some cases. There is undocumented behavior of the find_...() commands where they will not re-root the set of search locations where a search location starts with a ~ character (sorry if that is a really cryptic description, it comes from a longer discussion about cross-compilation in my book). This implies that ~ does get interpreted by find operations in at least some cases. You’d have to dig into the source code to ascertain exactly what those cases are, but cmFindCommon::RerootPaths() looks like the code related to the specific case I’m mentioning here.

I got the same problem with Emscripten toolchain, here’s also related discussion in Emscripten repository.

So the solution/workaround is to:

  • either set CMAKE_FIND_ROOT_PATH instead of CMAKE_PREFIX_PATH;
  • or keep CMAKE_PREFIX_PATH but set CMAKE_FIND_ROOT_PATH_MODE_PACKAGE to BOTH.

I am not sure if any of these variants is “correct” (because, I imagine, Emscripten toolchain disables this discovery for a reason), but that’s what got things working for me.