Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMakeLists does not honor INSTALL_PREFIX for CMake modules #2

Closed
severin-lemaignan opened this issue Sep 9, 2013 · 9 comments
Closed

Comments

@severin-lemaignan
Copy link

CMake modules (FindCorrade.cmake) are installed in CMAKE_ROOT:

set(CORRADE_CMAKE_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules)

Installing in CMAKE_ROOT is not a good practise (only Kitware-reviewed Find script are expected there).

http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:find_package lists the paths search by find_package.

I think a better option is ${CMAKE_INSTALL_PREFIX}/lib/cmake/${PROJECT_NAME}/

@mosra
Copy link
Owner

mosra commented Sep 9, 2013

Thanks for the info. I tried installing all the modules into ${CMAKE_INSTALL_PREFIX}/share/cmake/Corrade/. I had to rename FindCorrade.cmake to CorradeConfig.cmake and then the file was found as expected. However, the other CMake modules distributed with Corrade (UseCorrade.cmake and CorradeLibSuffix.cmake) weren't found if placed into given directory and the only working solution is to leave them in the original ${CMAKE_ROOT}/Modules directory.

Have you any solution how to make them available even if not installed in root module path? Explicitly adding ${CMAKE_INSTALL_PREFIX}/share/cmake/Corrade/ (or its equivalent) into CMAKE_MODULE_PATH seems more like an ugly workaround than proper solution to me.

@severin-lemaignan
Copy link
Author

Hum... Indeed, it must be rename corrade-config.cmake or CorradeConfig.cmake.

In which cases does it makes sense to use UseCorrade as a separate CMake script? wouldn't be possible to simple append it to FindCorrade.cmake? In that case, it leaves only CorradeLibSuffix.cmake alone, which can maybe also be merged...? what do you think?

@severin-lemaignan
Copy link
Author

Just to make the issue in my initial report more clear: by relying on CMAKE_ROOT to install CMake Find* scripts, you implicitly mandate admin rights for installation, which is a real problem :-/

@mosra
Copy link
Owner

mosra commented Sep 10, 2013

The admin rights is a problem I have frequently when installing on Windows and I circumvent that by making CMake module dir writable for given user. But I admit that it is not a solution at all :-)

I'm advising users to copy and distribute FindCorrade.cmake with their projects to avoid issues when Corrade might actually be installed, but its Find* module can't be found. It also avoids very verbose CMake error message, where instead of simply stating that "package is not found" it tells the user that some files and paths need to be adjusted. In my opinion that message should be targeted at library developer and not exposed to the user.

FindCorrade.cmake just finds the library files and then it includes UseCorrade.cmake. UseCorrade.cmake then does compiler configuration (enabling C++11 support etc.) and defines various macros. These macros are updated more frequently than FindCorrade.cmake and thus I put them to separate file so the user doesn't have to update the bundled Find* modules too often. CorradeLibSuffix.cmake is just one-off script to autodetect whether to install libraries in /usr/lib or /usr/lib64, saving the output to global LIB_SUFFIX variable. It might or might not need to be used and this way I'm leaving the decision on the user.

I searched around and indeed CMake packaging tutorial advises to install the *Config.cmake instead of Find*.cmake. However, for me it seems really counter-intutive: First, when placing CorradeConfig.cmake into CMAKE_MODULE_PATH (or FindCorrade.cmake into /usr/share/cmake/Corrade), the file isn't found. As the user needs to bundle the Find* module anyway, having exactly the same file under another name will lead to confusion. Second, cmake --help-module FindCorrade is really a nice way to obtain help for the module (with HTML conversion!), but it works only for the root module dir. It would be a pity if the two-page documentation in FindCorrade would be accessible only by direct examination of the file.

TL;DR: After some thinking around I'm proposing this solution:

  1. Don't install FindCorrade.cmake at all or make its installation optional (e.g. boolean WITH_FIND_MODULE), for example disabled by default to make the installation less annoying for new users. The user should still bundle it with the project, so not installing it won't do any harm. And if installed, leave it in ${CMAKE_ROOT}/Modules to avoid the two issues mentioned above. For packaging (i.e. where you don't want to have root privileges) make DESTDIR="..." install should be used anyway.
  2. Install UseCorrade.cmake and CorradeLibSuffix.cmake to e.g. ${CMAKE_INSTALL_PREFIX}/share/cmake/Corrade and let FindCorrade.cmake find them and put them into CMAKE_MODULE_PATH so they can be used without additional hassle.

By the way, for installations without root privileges (i.e. to non-standard location) I found something called Package Registry. Didn't try it yet, but it might solve some issues.

@severin-lemaignan
Copy link
Author

I'm probably missing something, but why would users bundle FindCorrade.cmake with their projects if CorradeConfig.cmake is installed and automagically found by CMake?

@mosra
Copy link
Owner

mosra commented Sep 10, 2013

If Corrade isn't installed, bundled FindCorrade.cmake fails with the following short and explanatory message (along with stack trace):

Could NOT find Corrade (missing: CORRADE_UTILITY_LIBRARY)

When there is no bundled Find* module, the message becomes rather cryptic and might hint that something is wrong with the user's project, while it's not. I occasionaly get bug report where user is confused by exactly the following and can't decode it into the simple message that Corrade needs to be installed:

By not providing "FindCorrade.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Corrade", but
CMake did not find one.

Could not find a package configuration file provided by "Corrade" with any
of the following names:

  CorradeConfig.cmake
  corrade-config.cmake

Add the installation prefix of "Corrade" to CMAKE_PREFIX_PATH or set
"Corrade_DIR" to a directory containing one of the above files.  If
"Corrade" provides a separate development package or SDK, be sure it has
been installed.

My understanding of it is that serious projects needs to bundle all Find* modules that aren't part of standard CMake installation to avoid these issues. This was actually mentioned as advised solution somewhere (can't find the link now). Moreover, I can't just install also modules for all dependencies (like FindSDL2.cmake, FindGLEW.cmake etc. needed by Magnum) to /usr/share/cmake/SDL2 etc., as they might cause conflicts. I need to bundle these with every project depending on them and then, in my opinion, it's not an issue whether to bundle two files or three.

@severin-lemaignan
Copy link
Author

So, conclusion: CMake does not provide good support for distributing projects' configuration... :-) Sorry for bothering you with that :-/

To be frank, I've always avoided the issue by generating and installing pkgconfig files instead. This is really simple and works well, except maybe for Windows (not sure how it is supported there).

Btw, SDL2 provides a pkgconfig file: s/find_package(SDL2)/pkg_search_module(SDL2 REQUIRED sdl2)/g replace the need for a FindSDL2.cmake (assuming it works on Windows, of course).

@mosra
Copy link
Owner

mosra commented Sep 10, 2013

No, sadly pkgconfig doesn't work on Windows. Actually, using "unixy" filesystem hierarchy and CMake's Find* modules on Windows works almost automagically; no juggling with registry or searching Program Files directories is needed and because all binaries are installed into the same directory, no PATH issues later when running applications.

Anyway, thanks for the discussion. I will implement the "optional" solution described above to avoid the issue with root privileges.

@mosra
Copy link
Owner

mosra commented Sep 12, 2013

Should be done in 664e859.

@mosra mosra closed this as completed Sep 12, 2013
mosra added a commit that referenced this issue Sep 22, 2013
…abled.

Until I made a fix for #2, KDevelop (and I hope also the other cool
IDEs) was able to parse the macros in `UseCorrade.cmake` and extract
targets and unit tests from calls to `corrade_add_test()`, among other
things. When I moved these macros from CMake's root module dir and put
them somewhere else, KDevelop wasn't able to find them anymore and thus
the targets didn't get detected, severely reducing the IDE experience
(i.e. no "one click" way to add new unit test target and run it through
debugger, no rebuild is triggered before running the executable etc.).

I can't expect KDevelop to reimplement `find_path()` command or
interpret all the CMake scripts to guess `CMAKE_MODULE_DIR` value from
which `UseCorrade.cmake` is included. Thus for now, until a better
solution is found, when `WITH_FIND_MODULE` is enabled, all the CMake
modules are installed into CMake's root module dir. This is completely
transparent to the user, no modiication in depending projects is needed
except for updating FindCorrade.cmake. But because this option is
disabled by default, the majority of existing code shouldn't be
affected.
@mosra mosra added this to the 2013.10 milestone Feb 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants