On Tuesday 14 February 2012, Alexander Neundorf wrote:
> On Tuesday 14 February 2012, Yury G. Kudryashov wrote:
> > Alexander Neundorf wrote:
> > > On Tuesday 14 February 2012, Yury G. Kudryashov wrote:
> > >> will substitute @PACKAGE_INCLUDE_INSTALL_DIR@ by "../../../include"
> > >> and @PACKAGE_MYPKGDATA_INSTALL_DIR@ by "../../../share/mypkg" (both
> > >> transformed to be relative to DESTINATION).
> > >
> > > A problem I see here (and which we discussed already before on kde-
> > > buildsystem) is the handling of the install() command.
> > >
> > > I thought a bit about a syntax like this, which I would like:
> > >
> > > configure_config_file(BarConfig.cmake.in BarConfig.cmake
> > >
> > > INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
> > > PATH_VARS INCLUDE_INSTALL_DIR DATA_INSTALL_DIR
> > > EXPORT_FILE BarExport.cmake)
> >
> > Why do you need EXPORT_FILE parameter? How can you use it? Include
> > automatically? Then you need VERSION_FILE parameter as well.
> >
> > > but this can't work, can it ?
> > >
> > > In the BarConfig.cmake file there would still be either a
> > >
> > > set(BAR_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@")
> > > which would work for absolute paths, or a
> > >
> > > set(BAR_INCLUDE_DIR "${SomePrefix}/@INCLUDE_INSTALL_DIR@")
> > > which would work only for relative paths, but a simple set() cannot
> > > work for both cases. Am I missing something ?
> >
> > You'll have in BarConfig.cmake.in
> > set(BAR_INCLUDE_DIR "@PACKAGE_HELPER_INCLUDE_INSTALL_DIR@)
> >
> > After configure_config_file() you'll have
> > # At top
> > get_filename_component(_PKG_CURRENT_DIR "${CURRENT_LIST_FILE}" PATH)
>
> Just a tip: since 2.8.3 or so there is ${CMAKE_CURRENT_LIST_DIR}
>
> > get_filename_component(_PKG_PREFIX_PATH "${_PKG_CURRENT_DIR}/../../.."
> > ABSOLUTE)
>
> The ../../../ will be also calculated by the macro, using RELATIVE_PATH and
> the DESTINATION parameter, right ?
>
> > #in place of your set()
> > set(BAR_INCLUDE_DIR "${_PKG_PREFIX_PATH}/include")
> >
> > > Do you have a working example ?
> >
> > Not yet. I think about something like this (not tested).
> >
> > foreach(var ${PACAKGE_HELPER_PATH_VARS})
> >
> > if(NOT DEFINED ${var})
> >
> > message(FATAL_ERROR ...)
> >
> > else if(IS_ABSOLUTE ${${var}})
> >
> > file(RELATIVE_PATH PACKAGE_HELPER_${var} ${CMAKE_INSTALL_PREFIX}
> >
> > ${${var}})
> >
> > else()
> >
> > set(PACKAGE_HELPER_${var} ${${var}})
> >
> > endif()
> >
> > endforeach()
> >
> > It would be nice to make those PACKAGE_HELPER_* vars local to
> > configure_config_file() function.
>
> If it's a function(), they are local automatically.
>
> Also still not tested, but now it should have the right prefix:
>
> foreach(var ${PACAKGE_HELPER_PATH_VARS})
> if(NOT DEFINED ${var})
> message(FATAL_ERROR ...)
> else if(IS_ABSOLUTE ${${var}})
> string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${_PKG_PREFIX_PATH}"
> PACKAGE_HELPER_${var} "${${var}}"
> else()
> set(PACKAGE_HELPER_${var} ${${var}})
> endif()
> else()
> set(PACKAGE_HELPER_${var} "\${_PKG_PREFIX_PATH}/${${var}}")
> endif()
> endforeach()
Ok, a working ConfigureConfigFile.cmake is attached, together with example
files, input and the configured output and the driving CMakeLists.txt.
The call now looks like this:
configure_config_file(BarConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake
INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
PATH_VARS INCLUDE_INSTALL_DIR
BIN_INSTALL_DIR
FOO_INSTALL_DIR ...
)
and in the Config.cmake.in file you have to put:
@CONFIG_HELPER_DIRS_INIT@
set_and_check(BAR_INCLUDE_DIR "@CONFIG_HELPER_INCLUDE_INSTALL_DIR@")
set(BAR_DATA_DIR "@CONFIG_HELPER_DATA_INSTALL_DIR@")
The set_and_check() macro is provided by the @CONFIG_HELPER_DIRS_INIT@, it
sets the variable and checks that the given directory or file exists.
IMO it's a bit much macro magic.
I'll also try an alternative approach tomorrow.
Comments ?
Alex
# set the version of myself
set(BAR_VERSION_MAJOR @BAR_VERSION_MAJOR@)
set(BAR_VERSION_MINOR @BAR_VERSION_MINOR@)
set(BAR_VERSION_PATCH @BAR_VERSION_PATCH@)
set(BAR_VERSION ${BAR_VERSION_MAJOR}.${BAR_VERSION_MINOR}.${BAR_VERSION_PATCH} )
# get_filename_component(CONFIG_PREFIX_DIR
"${CMAKE_CURRENT_LIST_DIR}/@CONFIG_RELATIVE_PATH@" ABSOLUTE)
@CONFIG_HELPER_DIRS_INIT@
set_and_check(BAR_INCLUDE_DIR "@CONFIG_HELPER_INCLUDE_INSTALL_DIR@")
set_and_check(BAR_BIN_DIR "@CONFIG_HELPER_BIN_INSTALL_DIR@")
set(BAR_DATA_DIR "@CONFIG_HELPER_DATA_INSTALL_DIR@")
set(BAR_BAR_DIR "@CONFIG_HELPER_BAR_INSTALL_DIR@")
set(BAR_FOO_DIR "@CONFIG_HELPER_FOO_INSTALL_DIR@")
# what is my include directory
set(BAR_INCLUDES "${BAR_INCLUDE_DIR}")
# import the exported targets
include(${CMAKE_CURRENT_LIST_DIR}/BarTargets.cmake)
# set the expected library variable
set(BAR_LIBRARIES bar )
cmake_minimum_required(VERSION 2.8.7)
project(Bar)
# the version number, needed for
# - the library version
# - version detection by cmake
set(BAR_VERSION_MAJOR 1)
set(BAR_VERSION_MINOR 2)
set(BAR_VERSION_PATCH 3)
set(BAR_VERSION ${BAR_VERSION_MAJOR}.${BAR_VERSION_MINOR}.${BAR_VERSION_PATCH} )
# set up install directories. INCLUDE_INSTALL_DIR and LIB_INSTALL_DIR must not be absolute paths
set(LIB_INSTALL_DIR_SUFFIX "" CACHE STRING "The directories where to install libraries to")
set(LIB_INSTALL_DIR lib${LIB_INSTALL_DIR_SUFFIX} )
set(CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/Bar )
# Use a versioned install directory for the headers so multiple versions can be installed in parallel
set(INCLUDE_INSTALL_DIR include )
# not changable, but we set a variable anyway for consistency
set(BIN_INSTALL_DIR bin)
set(DATA_INSTALL_DIR share/bar CACHE PATH "Where to install data files")
set(FOO_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/foo/abc )
set(BAR_INSTALL_DIR /opt/xyz/foo/abc )
# actually add the directory where the library is built
add_subdirectory(src)
# This "exports" all targets which have been put into the export set "BarExport".
# This means that cmake generates a file with the given filename, which can later on be loaded
# by projects using this package.
# This file contains add_library(bar IMPORTED) statements for each target in the export set, so
# when loaded later on cmake will create "imported" library targets from these, which can be used
# in many ways in the same way as a normal library target created via a normal add_library().
install(EXPORT BarExport DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE BarTargets.cmake )
# Create a BarConfig.cmake file. <name>Config.cmake files are searched by find_package()
# automatically. We configure that file so that we can put any information we want in it,
# e.g. version numbers, include directories, etc.
include(ConfigureConfigFile.cmake)
configure_config_file(BarConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake
INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
PATH_VARS INCLUDE_INSTALL_DIR
BIN_INSTALL_DIR
FOO_INSTALL_DIR
DATA_INSTALL_DIR
BAR_INSTALL_DIR
)
#configure_file(BarConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake @ONLY )
# Additionally, when cmake has found a BarConfig.cmake, it can check for a BarConfigVersion.cmake
# in the same directory when figuring out the version of the package when a version
# has been specified in the find_package() call, e.g. find_package(Bar 1.0)
include(WriteBasicConfigVersionFile)
write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/BarConfigVersion.cmake
VERSION ${BAR_VERSION}
COMPATIBILITY AnyNewerVersion )
# Install these two files into the same directory as the generated exports-file.
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/BarConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/BarConfigVersion.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
install(FILES README DESTINATION ${DATA_INSTALL_DIR})
include(CMakeParseArguments)
function(CONFIGURE_CONFIG_FILE _inputFile _outputFile)
set(oneValueArgs INSTALL_DESTINATION )
set(multiValueArgs PATH_VARS )
cmake_parse_arguments(CCF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(CCF_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to CONFIGURE_CONFIG_FILE(): \"${CCF_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT CCF_INSTALL_DESTINATION)
message(FATAL_ERROR "No INSTALL_DESTINATION given to CONFIGURE_CONFIG_FILE()")
endif()
if(NOT IS_ABSOLUTE "${CCF_INSTALL_DESTINATION}")
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
endif()
file(RELATIVE_PATH CONFIG_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
message(STATUS "abs: -${absInstallDir}- REL: -${CONFIG_RELATIVE_PATH}-")
foreach(var ${CCF_PATH_VARS})
message(STATUS "proc ${var} = -${${var}}-")
if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} does not exist")
else()
if(IS_ABSOLUTE "${${var}}")
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${CONFIG_PREFIX_DIR}"
CONFIG_HELPER_${var} "${${var}}")
else()
set(CONFIG_HELPER_${var} "\${CONFIG_PREFIX_DIR}/${${var}}")
endif()
endif()
message(STATUS "CONFIG_HELPER_${var} = -${CONFIG_HELPER_${var}}-")
endforeach()
set(CONFIG_HELPER_DIRS_INIT "
####### Expanded from @CONFIG_HELPER_DIRS_INIT@ by ConfigureConfigFile.cmake #######
get_filename_component(CONFIG_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${CONFIG_RELATIVE_PATH}\" ABSOLUTE)
macro(set_and_check _var _file)
set(\${_var} \"\${_file}\")
if(NOT EXISTS \"\${_file}\")
message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
endif()
endmacro()
####################################################################################
")
configure_file("${_inputFile}" "${_outputFile}" @ONLY)
endfunction()
# set the version of myself
set(BAR_VERSION_MAJOR 1)
set(BAR_VERSION_MINOR 2)
set(BAR_VERSION_PATCH 3)
set(BAR_VERSION ${BAR_VERSION_MAJOR}.${BAR_VERSION_MINOR}.${BAR_VERSION_PATCH} )
# get_filename_component(CONFIG_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
####### Expanded from @CONFIG_HELPER_DIRS_INIT@ by ConfigureConfigFile.cmake #######
get_filename_component(CONFIG_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
macro(set_and_check _var _file)
set(${_var} "${_file}")
if(NOT EXISTS "${_file}")
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
endif()
endmacro()
####################################################################################
set_and_check(BAR_INCLUDE_DIR "${CONFIG_PREFIX_DIR}/include")
set(BAR_BIN_DIR "${CONFIG_PREFIX_DIR}/bin")
set(BAR_DATA_DIR "${CONFIG_PREFIX_DIR}/share/bar")
set(BAR_BAR_DIR "/opt/xyz/foo/abc")
set(BAR_FOO_DIR "${CONFIG_PREFIX_DIR}/foo/abc")
# what is my include directory
set(BAR_INCLUDES "${BAR_INCLUDE_DIR}")
# import the exported targets
include(${CMAKE_CURRENT_LIST_DIR}/BarTargets.cmake)
# set the expected library variable
set(BAR_LIBRARIES bar )
--
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the CMake FAQ at:
http://www.cmake.org/Wiki/CMake_FAQ
Follow this link to subscribe/unsubscribe:
http://public.kitware.com/cgi-bin/mailman/listinfo/cmake-developers