[cmake-developers] Making _IMPORT_PREFIX from an installed exports-file available to an including file

Michael Wild themiwi at gmail.com
Sun Jun 5 05:50:12 EDT 2011


On 06/04/2011 10:28 PM, Alexander Neundorf wrote:
> Hi,
> 
> when installing an export-file cmake has the nice feature to calculate the 
> CMAKE_INSTALL_PREFIX from the current location:
> 
> -------------8<------------------8<----------8<----------------
> # 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)
> GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
> GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
> GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
> 
> # Import target "bar" for configuration ""
> SET_PROPERTY(TARGET bar APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
> ...
> 
> # Cleanup temporary variables.
> SET(_IMPORT_PREFIX)
> -------------8<------------------8<----------8<----------------
> 
> 
> I can't do this in cmake-script in a FooConfig.cmake file myself, there I 
> simply must assume that if I go four levels up that I have reached my install 
> prefix. This will usually be correct, but it would be nicer if I could reuse 
> this knowledge which cmake generates into the per-configuration files.
> 
> So, I'd like to do from my FooConfig.cmake file something like:
> 
> include(${CMAKE_CURRENT_LIST_DIR}/FooExports.cmake)
> set(FOO_INCLUDE_DIR ${FooExports_IMPORT_PREFIX}/include )
> 
> Related to this, why is this location computed in the configuration-specific 
> file, and not once in the "parent" exports-file, which includes all the 
> export-files for the different configurations ?
> The files which will be included are collected with this call:
> FILE(GLOB CONFIG_FILES "${_DIR}/BarTargets-*.cmake")
> 
> I.e. it is guaranteed that they are all in the same directory as the including 
> file.
> Doesn't that mean that they are also in the same directory relative to their 
> respective install prefix ?
> 
> If so, would it be ok if I move the code for calculating the IMPORT_PREFIX 
> into the "parent" exports file ?
> 
> Or should I add basically the same code in the generated "parent" exports-file 
> ?
> 
> Alex


I usually hard-code the relative path from the FooConfig.cmake file to
the install-prefix and other installation directories using
configure_file(). E.g:

CMakeLists.txt:
------------8<--------------
# ...

set(INSTALL_BIN_DIR bin CACHE PATH
  "Installation directory for runtime binaries")
set(INSTALL_LIB_DIR lib CACHE PATH
  "Installation directory for libraries")
set(INSTALL_INCLUDE_DIR include CACHE PATH
  "Installation directory for headers")
if(WIN32 AND NOT CYGWIN)
  set(DEF_INSTALL_CMAKE_DIR CMake)
  set(DEF_INSTALL_DATA_DIR data)
else()
  set(DEF_INSTALL_CMAKE_DIR share/Foo)
  set(DEF_INSTALL_CMAKE_DIR share/Foo/CMake)
endif()
set(INSTALL_DATA_DIR ${DEF_INSTALL_DATA_DIR} CACHE PATH
  "Installation directory for data files")
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH
  "Installation directory for CMake files")
file(RELATIVE_PATH CONF_REL_INSTALL_PREFIX "${INSTALL_CMAKE_DIR}"
    "${CMAKE_INSTALL_PREFIX}")
foreach(v BIN LIB INCLUDE DATA)
  if(NOT IS_ABSOLUTE "${INSTALL_${v}_DIR}")
    set(INSTALL_${v}_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_${v}_DIR}")
  endif()
  file(RELATIVE_PATH CONF_REL_${v}_DIR "${INSTALL_CMAKE_DIR}"
      "${INSTALL_${v}_DIR}")
endforeach()

configure_file(FooConfig.cmake.in
    "${PROJECT_BINARY_DIR}/CMake/FooConfig.cmake" @ONLY)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")

set(FOO_HDRS
  include/foo.h
  include/bar.h
  include/baz.h)
# copy headers into build tree so we don't have to embed the
# PROJECT_SOURCE_DIR variable in the FooConfig.cmake file
foreach(h IN LISTS FOO_HDRS)
  get_filename_component(hh "${h}" NAME)
  configure_file(${h} "${PROJECT_BINARY_DIR}/include/${hh}" COPYONLY)
endforeach()

#...
------------8<--------------

FooConfig.cmake.in:
------------8<--------------
# ...

get_filename_component(FOO_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
if(EXISTS "${_FOO_CMAKE_DIR}/../CMakeCache.txt")
  # in build tree
  get_filename_component(FOO_INSTALL_PREFIX "${FOO_CMAKE_DIR}" PATH)
  set(FOO_BIN_DIR "${_FOO_PREFIX}/bin")
  set(FOO_LIB_DIR "${_FOO_PREFIX}/lib")
  set(FOO_INCLUDE_DIR "${_FOO_PREFIX}/include")
else()
  set(FOO_INSTALL_PREFIX "${FOO_CMAKE_DIR}/@CONF_REL_INSTALL_PREFIX@")
  set(FOO_BIN_DIR "${FOO_CMAKE_DIR}/@CONF_REL_BIN_DIR@")
  set(FOO_LIB_DIR "${FOO_CMAKE_DIR}/@CONF_REL_LIB_DIR@")
  set(FOO_INCLUDE_DIR "${FOO_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@")
endif()

# ...
------------8<--------------

Of course, this is all from memory and only should illustrate the way
that works best for me...

HTH

Michael



More information about the cmake-developers mailing list