Skip to content

Commit

Permalink
refactored catkin_package() / catkin_package_export() to use only one…
Browse files Browse the repository at this point in the history
… in the common case
  • Loading branch information
dirk-thomas committed Sep 24, 2012
1 parent e59200a commit 3a3cc5c
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 354 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ if(NOT DEFINED CATKIN_TOPLEVEL)
endif()

catkin_package()
catkin_package_export()

# for backward compatibility we provide ROSConfig(-version).cmake files
assert(CATKIN_BUILD_PREFIX)
Expand Down
2 changes: 1 addition & 1 deletion cmake/all.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ foreach(filename
catkin_add_env_hooks
catkin_generate_environment
catkin_package
catkin_package_export
catkin_package_xml
catkin_workspace
debug_message
em_expand
Expand Down
314 changes: 271 additions & 43 deletions cmake/catkin_package.cmake
Original file line number Diff line number Diff line change
@@ -1,64 +1,292 @@
#
# Process :ref:`package.xml` from ``CMAKE_CURRENT_SOURCE_DIR`` and
# make several information available to CMake.
# It installs the package.xml file, and it generates code for
# ``find_package`` and ``pkg-config`` so that other packages can get
# information about this package. For this purpose the information
# about include directories, libraries, further dependencies and
# CMake variables are used.
#
# .. note:: It must be called once in each package, after calling
# project() where the project name must match the package name and
# before calling `catkin_package_export()`, to ensure that
# auto-generated CMake and pkg-config files contain correct version
# information. Best practice is to call this macro early in your
# root CMakeLists.txt, immediately after calling ``project()`` and
# .. note:: It must be called once for each package. Best practice
# is to call this macro early in your root CMakeLists.txt,
# immediately after calling ``project()`` and
# ``find_package(catkin REQUIRED)``.
#
# It installs ``package.xml`` to ``share/${PROJECT_NAME}``.
# :param INCLUDE_DIRS: ``CMAKE_CURRENT_SOURCE_DIR``-relative paths to
# C/C++ includes
# :type INCLUDE_DIRS: list of strings
# :param LIBRARIES: names of library targets that will appear in the
# ``catkin_LIBRARIES`` and ``${PROJECT_NAME}_LIBRARIES`` of other
# projects that search for you via ``find_package``. Currently
# this will break if the logical target names are not the same as
# the installed names.
# :type LIBRARIES: list of strings
# :param DEPENDS: a list of CMake projects which this project depends
# on. It is used when client code finds this project via
# ``find_package()``. Each project listed will in turn be
# ``find_package``\ -ed and their ``INCLUDE_DIRS`` and ``LIBRARIES``
# will be appended to ours. Only projects should be used where we
# can guarantee that they are *find_packagable*. If they are not
# catkin packages they are not added to the ``requires`` list in
# the pkg-config file since we can not ensure that they are
# *package_configurable*.
# :type DEPENDS: list of strings
# :param CFG_EXTRAS: a CMake file containing extra stuff that should
# be accessible to users of this package after
# ``find_package``\ -ing it. This file must live in the
# subdirectory ``cmake`` and must have the additional extension
# ``.in`` (since it is expanded using CMake's ``configure_file()``).
# The template can distinguish between build- and installspace
# using the boolean variables ``BUILDSPACE`` and ``INSTALLSPACE``
# and should be verified to work in both cases.
# :type CFG_EXTRAS: string
#
# :outvar <packagename>_VERSION: the version number
# :outvar <packagename>_MAINTAINER: the name and email of the maintainer(s)
# :outvar <packagename>_DEPENDS: the build dependencies
# :outvar CATKIN_PACKAGE_BIN_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_BIN_DESTINATION`.
# :outvar CATKIN_PACKAGE_ETC_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_ETC_DESTINATION`.
# :outvar CATKIN_PACKAGE_INCLUDE_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_INCLUDE_DESTINATION`.
# :outvar CATKIN_PACKAGE_LIB_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_LIB_DESTINATION`.
# :outvar CATKIN_PACKAGE_PYTHON_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_PYTHON_DESTINATION`.
# :outvar CATKIN_PACKAGE_SHARE_DESTINATION:
# See :cmake:data:`CATKIN_PACKAGE_SHARE_DESTINATION`.
#
# :outvar CATKIN_GLOBAL_BIN_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_BIN_DESTINATION`.
# :outvar CATKIN_GLOBAL_ETC_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_ETC_DESTINATION`.
# :outvar CATKIN_GLOBAL_INCLUDE_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_INCLUDE_DESTINATION`.
# :outvar CATKIN_GLOBAL_LIB_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_LIB_DESTINATION`.
# :outvar CATKIN_GLOBAL_LIBEXEC_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_LIBEXEC_DESTINATION`.
# :outvar CATKIN_GLOBAL_PYTHON_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_PYTHON_DESTINATION`.
# :outvar CATKIN_GLOBAL_SHARE_DESTINATION:
# See :cmake:data:`CATKIN_GLOBAL_SHARE_DESTINATION`.
#
# Example:
# ::
#
# catkin_package(
# INCLUDE_DIRS include
# LIBRARIES proj-one proj-two
# DEPENDS roscpp
# CFG_EXTRAS proj-extras.cmake
# )
#
# @public
#
macro(catkin_package)
debug_message(10 "catkin_package() called in file ${CMAKE_CURRENT_LIST_FILE}")

# verify that no arguments are passed
if(ARGN)
message(FATAL_ERROR "catkin_package() does not support arguments")
# call catkin_package_xml() if it has not been called manually before
if(NOT _CATKIN_CURRENT_PACKAGE)
catkin_package_xml()
endif()

# verify that project() has been called before
if(NOT PROJECT_NAME)
message(FATAL_ERROR "catkin_package() PROJECT_NAME is not set. You must call project() before you can call catkin_package().")
#
# BUILD AND INSTALL DESTINATIONS
#

# set project specific output directory for libraries
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CATKIN_BUILD_PREFIX}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CATKIN_BUILD_PREFIX}/lib)
# set project specific output directory for binaries
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CATKIN_BUILD_PREFIX}/lib/${PROJECT_NAME})

# set global install destinations
set(CATKIN_GLOBAL_BIN_DESTINATION bin)
set(CATKIN_GLOBAL_ETC_DESTINATION etc)
set(CATKIN_GLOBAL_INCLUDE_DESTINATION include)
set(CATKIN_GLOBAL_LIB_DESTINATION lib)
set(CATKIN_GLOBAL_LIBEXEC_DESTINATION lib)
set(CATKIN_GLOBAL_PYTHON_DESTINATION ${PYTHON_INSTALL_DIR})
set(CATKIN_GLOBAL_SHARE_DESTINATION share)

# set project specific install destinations
set(CATKIN_PACKAGE_BIN_DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}/${PROJECT_NAME})
set(CATKIN_PACKAGE_ETC_DESTINATION ${CATKIN_GLOBAL_ETC_DESTINATION}/${PROJECT_NAME})
set(CATKIN_PACKAGE_INCLUDE_DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}/${PROJECT_NAME})
set(CATKIN_PACKAGE_LIB_DESTINATION ${CATKIN_GLOBAL_LIB_DESTINATION})
set(CATKIN_PACKAGE_PYTHON_DESTINATION ${CATKIN_GLOBAL_PYTHON_DESTINATION}/${PROJECT_NAME})
set(CATKIN_PACKAGE_SHARE_DESTINATION ${CATKIN_GLOBAL_SHARE_DESTINATION}/${PROJECT_NAME})

_catkin_package(${ARGN})
endmacro()

function(_catkin_package)
parse_arguments(PROJECT
"INCLUDE_DIRS;LIBRARIES;CFG_EXTRAS;DEPENDS"
""
${ARGN})
if(PROJECT_DEFAULT_ARGS)
message(FATAL_ERROR "catkin_package() called with unused arguments: ${PROJECT_DEFAULT_ARGS}")
endif()

# ensure that function is not called multiple times per package
if(DEFINED _CATKIN_CURRENT_PACKAGE)
message(FATAL_ERROR "catkin_package(): in '${CMAKE_CURRENT_LIST_FILE}', _CATKIN_CURRENT_PACKAGE is already set (to: ${_CATKIN_CURRENT_PACKAGE}). This should not be the case.")
# unset previously found directory of this package, so that this package overlays the other cleanly
if(${PROJECT_NAME}_DIR)
set(${PROJECT_NAME}_DIR "" CACHE PATH "" FORCE)
endif()

# stamp and parse package.xml
stamp(${CMAKE_CURRENT_SOURCE_DIR}/package.xml)
safe_execute_process(COMMAND ${PYTHON_EXECUTABLE}
${catkin_EXTRAS_DIR}/parse_package_xml.py
${CMAKE_CURRENT_SOURCE_DIR}/package.xml
${PROJECT_BINARY_DIR}/catkin_generated/package.cmake)
# load extracted variable into cmake
include(${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/package.cmake)

# verify that the package name from package.xml equals the project() name
if(NOT _CATKIN_CURRENT_PACKAGE STREQUAL PROJECT_NAME)
message(FATAL_ERROR "catkin_package_export() package name in package.xml '${_CATKIN_CURRENT_PACKAGE}' does not match current PROJECT_NAME '${PROJECT_NAME}'. You must call project() with the same name before.")
# filter out DEPENDS which have not been find_package()-ed before
foreach(depend ${PROJECT_DEPENDS})
if(NOT ${depend}_FOUND)
message(WARNING "catkin_package(${PROJECT_NAME}) depends on '${depend}' which has not been find_package()-ed before")
list(REMOVE_ITEM PROJECT_DEPENDS ${depend})
endif()
endforeach()

# find catkin-only packages in DEPENDS list for use in .pc files
set(PROJECT_CATKIN_DEPENDS "")
foreach(depend ${PROJECT_DEPENDS})
if(${${depend}_FOUND_CATKIN_PROJECT})
list(APPEND PROJECT_CATKIN_DEPENDS ${depend})
endif()
endforeach()

# package version provided by package.cmake/xml
set(PROJECT_VERSION ${${PROJECT_NAME}_VERSION})

# get library paths from all workspaces
set(lib_paths "")
foreach(workspace ${CATKIN_WORKSPACES})
list_append_unique(lib_paths ${workspace}/lib)
endforeach()

#
# BUILDSPACE
#

set(BUILDSPACE TRUE)
set(INSTALLSPACE FALSE)

set(PROJECT_SPACE_DIR ${CATKIN_BUILD_PREFIX})
set(PKG_INCLUDE_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})

# absolute path to include dirs and validate that they are existing either absolute or relative to packages source
set(PROJECT_ABSOLUTE_INCLUDE_DIRS "")
foreach(idir ${PROJECT_INCLUDE_DIRS})
if(IS_ABSOLUTE ${idir} AND IS_DIRECTORY ${idir})
set(include ${idir})
elseif(IS_DIRECTORY ${PKG_INCLUDE_PREFIX}/${idir})
set(include ${PKG_INCLUDE_PREFIX}/${idir})
else()
message(FATAL_ERROR "catkin_package include dir '${idir}' is neither an absolute directory nor exists relative to '${CMAKE_CURRENT_SOURCE_DIR}'")
endif()
list(APPEND PROJECT_ABSOLUTE_INCLUDE_DIRS ${include})
endforeach()

# prepend library path of this workspace
set(PKG_CONFIG_LIB_PATHS ${lib_paths})
list(INSERT PKG_CONFIG_LIB_PATHS 0 ${PROJECT_SPACE_DIR}/lib)
set(PKG_CMAKE_DIR ${PROJECT_SPACE_DIR}/share/${PROJECT_NAME}/cmake)

# ensure that output folder exists
file(MAKE_DIRECTORY ${CATKIN_BUILD_PREFIX}/lib/pkgconfig)
# generate buildspace pc for project
em_expand(${catkin_EXTRAS_DIR}/templates/pkg.context.pc.in
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/pkg.buildspace.context.pc.py
${catkin_EXTRAS_DIR}/em/pkg.pc.em
${CATKIN_BUILD_PREFIX}/lib/pkgconfig/${PROJECT_NAME}.pc)

# generate buildspace config for project
set(infile ${${PROJECT_NAME}_EXTRAS_DIR}/${PROJECT_NAME}Config.cmake.in)
if(NOT EXISTS ${infile})
set(infile ${catkin_EXTRAS_DIR}/templates/pkgConfig.cmake.in)
endif()
configure_file(${infile}
${CATKIN_BUILD_PREFIX}/share/${PROJECT_NAME}/cmake/${PROJECT_NAME}Config.cmake
@ONLY
)

# generate buildspace config-version for project
configure_file(${catkin_EXTRAS_DIR}/templates/pkgConfig-version.cmake.in
${CATKIN_BUILD_PREFIX}/share/${PROJECT_NAME}/cmake/${PROJECT_NAME}Config-version.cmake
@ONLY
)

# generate buildspace cfg-extras for project
foreach(extra ${PROJECT_CFG_EXTRAS})
assert_file_exists(${CMAKE_CURRENT_SOURCE_DIR}/cmake/${extra}.in "Nonexistent extra")
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/${extra}.in
configure_file(cmake/${extra}.in
${CATKIN_BUILD_PREFIX}/share/${PROJECT_NAME}/cmake/${extra}
@ONLY
)
endforeach()

# install package.xml
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/package.xml
DESTINATION share/${PROJECT_NAME})
#
# INSTALLSPACE
#

# automatically chain dependencies for meta-packages
if(${_CATKIN_CURRENT_PACKAGE_IS_META})
set(_CATKIN_PACKAGE_EXPORT_CALLED_INTERNALLY TRUE)
find_package(catkin REQUIRED COMPONENTS ${${PROJECT_NAME}_DEPENDS})
catkin_package_export(DEPENDS ${${PROJECT_NAME}_DEPENDS})
unset(_CATKIN_PACKAGE_EXPORT_CALLED_INTERNALLY)
set(BUILDSPACE FALSE)
set(INSTALLSPACE TRUE)

set(PROJECT_SPACE_DIR ${CMAKE_INSTALL_PREFIX})
set(PKG_INCLUDE_PREFIX ${PROJECT_SPACE_DIR})

# absolute path to include dir under install prefix if any include dir is set
set(PROJECT_ABSOLUTE_INCLUDE_DIRS "")
if(${PROJECT_INCLUDE_DIRS})
set(PROJECT_ABSOLUTE_INCLUDE_DIRS ${PKG_INCLUDE_PREFIX}/include)
endif()
endmacro()

# prepend library path of this workspace
set(PKG_CONFIG_LIB_PATHS ${lib_paths})
list(INSERT PKG_CONFIG_LIB_PATHS 0 ${PROJECT_SPACE_DIR}/lib)
set(PKG_CMAKE_DIR ${PROJECT_SPACE_DIR}/share/${PROJECT_NAME}/cmake)

# ensure that output folder exists
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace)
# generate and install pc for project
em_expand(${catkin_EXTRAS_DIR}/templates/pkg.context.pc.in
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/pkg.installspace.context.pc.py
${catkin_EXTRAS_DIR}/em/pkg.pc.em
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}.pc
DESTINATION lib/pkgconfig
)

# generate config for project
set(infile ${${PROJECT_NAME}_EXTRAS_DIR}/${PROJECT_NAME}Config.cmake.in)
if(NOT EXISTS ${infile})
set(infile ${catkin_EXTRAS_DIR}/templates/pkgConfig.cmake.in)
endif()
configure_file(${infile}
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}Config.cmake
@ONLY
)

# generate config-version for project
set(infile ${${PROJECT_NAME}_EXTRAS_DIR}/${PROJECT_NAME}Config-version.cmake.in)
if(NOT EXISTS ${infile})
set(infile ${catkin_EXTRAS_DIR}/templates/pkgConfig-version.cmake.in)
endif()
configure_file(${infile}
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}Config-version.cmake
@ONLY
)

# generate cfg-extras for project
set(installable_cfg_extras "")
foreach(extra ${PROJECT_CFG_EXTRAS})
list(APPEND installable_cfg_extras ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${extra})
configure_file(cmake/${extra}.in
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${extra}
@ONLY
)
endforeach()

# install config, config-version and cfg-extras for project
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/installspace/${PROJECT_NAME}Config-version.cmake
${installable_cfg_extras}
DESTINATION share/${PROJECT_NAME}/cmake
)

# XXXX generate manifest.xml for backward compatibility
endfunction()
Loading

0 comments on commit 3a3cc5c

Please sign in to comment.