CMake's find_package ignores the PATHS option when building for iOS

Viewed 653

Library "foo" depends on library "bar". Both libraries' build system is based on CMake. Library "bar" provides a CMake package that downstream projects, such as library "foo", can use.

"foo" integrates "bar" via Git submodule. "foo" expects that "bar" is built and installed in the submodule path in a specific location. This is how the folder structure looks like:

/path/to/foo
+-- bar                  <-- "bar" Git submodule
|   +-- build            <-- "bar" out-of-source build folder
|       +-- install      <-- "bar" installation folder
+-- build                <-- "foo" out-of-source build folder
+-- CMakeLists.txt

Here's a minimalistic CMakeLists.txt for "foo" that shows the find_package call I'm using:

project ( foo )
set ( BAR_INSTALLATION_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/bar/build/install" )
find_package (
  bar
  0.1
  EXACT
  QUIET
  PATHS ${BAR_INSTALLATION_PREFIX}
)

This works fine, i.e. find_package finds "bar", as long as I build "foo" for the host platform macOS. When I try to cross-compile "foo" for iOS, however, find_package fails to find "bar".

I used -DCMAKE_FIND_DEBUG_MODE=ON to diagnose the problem, and it appears that find_package is simply ignoring the folder that is specified for the PATHS option. This is the minimalistic command line that I have arrived at during diagnosis that still exhibits the problem:

cmake .. -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_FIND_DEBUG_MODE=ON

And here's the relevant part of the output that I'm seeing:

  [...]
  Paths specified by the find_package PATHS option.
    /Users/patrick/dev/foo/bar/build/install

  find_package considered the following locations for the Config module:

    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/barConfig.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/bar-config.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/barConfig.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/bar-config.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/barConfig.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/usr/bar-config.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/barConfig.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/bar-config.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/barConfig.cmake
    /Applications/Xcode-11.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/bar-config.cmake

  The file was not found.
  [...]

As can be seen find_package initially recognizes the PATHS option value, but then it ignores the folder when it actually performs the package search in the file system.

How can I tell find_package to not ignore the folder specified to the PATHS option when cross-compiling for iOS?

Environment: macOS 10.14.6, Xcode 11.2.1, CMake 3.19.2 (installed via Homebrew).

2 Answers

I currently have added this to my CMakeLists.txt, between where I'm setting BAR_INSTALLATION_PREFIX and where I'm invoking find_package:

if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
  set ( bar_DIR "${BAR_INSTALLATION_PREFIX}/lib/bar" )
endif()

This sets the <PackageName>_DIR variable to the concrete folder where the package's config file (bar-config.cmake) is located. According to the CMake docs this can also be set as an environment variable.

It's not pretty, and it couples project "foo" to its dependency "bar" more than I would like, but as a workaround it will do for the moment.

I'm not marking this answer as "accepted" in case someone with more CMake knowledge comes up with a real solution.

For iOS and Android, CMake sets the CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMake variable to ONLY by default. That is, all the PATHS that you set are only resolved within CMAKE_FIND_ROOT_PATH.

If you want find_package() to resolve the paths also as host paths, you have to manually set CMAKE_FIND_ROOT_PATH_MODE_PACKAGE either to NEVER or BOTH.

Related