10

In general, relative parameters of type PATH, like "lib" or "source/include" are resolved in CMake to an absolute path using current value of variables, like for instance: ${CMAKE_INSTALL_PREFIX} in case of command INSTALL. This, however, does not work if I would like to use empty relative path (or not set it at all), so that the resulting absolute path was equal to ${CMAKE_INSTALL_PREFIX} - CMake generator would complain about non existing DESTINATION, although there is no reason why it couldn't be resolved.

I know two workarounds to this issue, but the both have their flaws which prevent me from achieving my goal:

  1. Use ${CMAKE_INSTALL_PREFIX} as the DESTINATION value. This correctly resolved the path, but in case of INSTALL(EXPORT), paths in generated Target.cmake are absolute, which makes the package not relocatable.
  2. Use . as the DESTINATION. This at least generates relative paths inside Target.cmake, but the paths are incorrect. . is apparently considered as a regular folder, and in the process of Target.cmake generation, when _IMPORT_PREFIX is determined, CMake strips one folder component too much:

    # Compute the installation prefix relative to this file.
    get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
    get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
    

Is there any other workaround? Do you think that lack of empty relative paths could be considered a bug?

usr1234567
  • 21,601
  • 16
  • 108
  • 128
Piotr G
  • 959
  • 1
  • 7
  • 25
  • What's your CMake version? – usr1234567 Aug 19 '17 at 08:19
  • 3.8, but has this changed over cmake versions? – Piotr G Aug 19 '17 at 12:49
  • I have same problem and I just found your question after reviewing what is happening during export file generation in cmake source code. So I think there is no option to just generate export where _IMPORT_PREFIX is simply set to "${CMAKE_CURRENT_LIST_FILE}". I dont know why, for me it also seems to be pretty common use case where you have a package with library binaries, include files and cmake export file to import it, and it dont have to be hard pinned somewhere in the filesystem. – Marek Kijo Jan 18 '19 at 21:12

2 Answers2

0

I think I found some hacky solution for that. This will force cmake to generate the export file where _IMPORT_PREFIX is set to current location of the exported cmake. Right before the install and export sequence modify CMAKE_INSTALL_PREFIX like this:

set(CMAKE_INSTALL_PREFIX "\${CMAKE_CURRENT_LIST_FILE}/..")

The \ sign before ${CMAKE_CURRENT_LIST_FILE} prevents from evaluating variable reference ${CMAKE_CURRENT_LIST_FILE} at this point, it is just passed as a string. After that in exported cmake you will get:

set(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}/..")

You need to add /.. at the end because set function will set the _IMPORT_PREFIX as a whole path to exported cmake, together with the cmake file name (eg. C:/Works/project/ext/library/Library.cmake) so the /.. will drop /Library.cmake. Perfect result would be to just force cmake to use get_filename_component in exported file, like:

get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)

But as I mentioned in a comment it is probably impossible regarding cmake implementation.

I don't know if modifying CMAKE_INSTALL_PREFIX has no any negative side effects. On UNIX platform you can try to use DESTDIR instead of CMAKE_INSTALL_PREFIX as an argument for make, but I haven't tried that.

Marek Kijo
  • 173
  • 1
  • 9
0

CMAKE_CURRENT_LIST_DIR works for me. Without the necessity of adding the /...

@[Marek Kijo] - thanks for your solution with: set(CMAKE_INSTALL_PREFIX "\${CMAKE_CURRENT_LIST_FILE}/..")

darkbit
  • 31
  • 3