1#
2# Search all subfolders in the workspace for ``package.xml`` files.
3# Based on the dependencies specified in the ``build_depends``,
4# ``buildtool_depends`` and (as of package format version 2)
5# ``test_depends`` tags it performs a topological sort and calls
6# ``add_subdirectory()`` for each directory.
7#
8# The functions is only called in catkin's ``toplevel.cmake``, which
9# is usually symlinked to the workspace root directory (which
10# contains multiple packages).
11#
12function(catkin_workspace)
13  debug_message(10 "catkin_workspace() called in file '${CMAKE_CURRENT_LIST_FILE}'")
14
15  # set global output directories for artifacts and create them if necessary
16  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/lib)
17  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/lib)
18  if(NOT IS_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
19    file(MAKE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
20  endif()
21
22  # tools/libraries.cmake
23  configure_shared_library_build_settings()
24
25  set(CATKIN_WHITELIST_PACKAGES "" CACHE STRING "List of ';' separated packages to build")
26  set(CATKIN_BLACKLIST_PACKAGES "" CACHE STRING "List of ';' separated packages to exclude")
27  if(NOT "${CATKIN_WHITELIST_PACKAGES}" STREQUAL "")
28    message(STATUS "Using CATKIN_WHITELIST_PACKAGES: ${CATKIN_WHITELIST_PACKAGES}")
29  endif()
30  if(NOT "${CATKIN_BLACKLIST_PACKAGES}" STREQUAL "")
31    message(STATUS "Using CATKIN_BLACKLIST_PACKAGES: ${CATKIN_BLACKLIST_PACKAGES}")
32  endif()
33
34  assert(catkin_EXTRAS_DIR)
35  em_expand(
36    ${catkin_EXTRAS_DIR}/templates/order_packages.context.py.in
37    ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/order_packages.py
38    ${catkin_EXTRAS_DIR}/em/order_packages.cmake.em
39    ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/order_packages.cmake
40    )
41  debug_message(10 "catkin_workspace() including order_packages.cmake")
42  include(${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/order_packages.cmake)
43
44  if(CATKIN_ORDERED_PACKAGES)
45    set(CATKIN_NONCONFORMANT_METAPACKAGE FALSE)
46    set(CATKIN_NONHOMOGENEOUS_WORKSPACE FALSE)
47    list(LENGTH CATKIN_ORDERED_PACKAGES count)
48    message(STATUS "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
49    message(STATUS "~~  traversing ${count} packages in topological order:")
50    math(EXPR range "${count} - 1")
51    foreach(index RANGE ${range})
52      list(GET CATKIN_ORDERED_PACKAGES ${index} name)
53      list(GET CATKIN_ORDERED_PACKAGE_PATHS ${index} path)
54      list(GET CATKIN_ORDERED_PACKAGES_IS_META ${index} is_meta)
55      list(GET CATKIN_ORDERED_PACKAGES_BUILD_TYPE ${index} build_type)
56      if(${is_meta})
57        message(STATUS "~~  - ${name} (metapackage)")
58        # verify that CMakeLists.txt of metapackage conforms to standard
59        set(metapackage_arguments "")
60        assert(CATKIN_METAPACKAGE_CMAKE_TEMPLATE)
61        configure_file(${CATKIN_METAPACKAGE_CMAKE_TEMPLATE}
62          ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/metapackages/${name}/CMakeLists.txt
63          @ONLY)
64        if(EXISTS ${CMAKE_SOURCE_DIR}/${path}/CMakeLists.txt)
65          # compare CMakeLists.txt with standard content
66          file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/metapackages/${name}/CMakeLists.txt generated_cmakelists)
67          # allow any of CMake minimum version
68          string(REPLACE "2.8.3" "[0-9]+\\.[0-9]+\\.[0-9]+" generated_cmakelists_pattern "${generated_cmakelists}")
69          # need to escape parenthesis
70          string(REPLACE "(" "\\(" generated_cmakelists_pattern "${generated_cmakelists_pattern}")
71          string(REPLACE ")" "\\)" generated_cmakelists_pattern "${generated_cmakelists_pattern}")
72          file(STRINGS ${path}/CMakeLists.txt existing_cmakelists)
73          if(NOT "${existing_cmakelists}" MATCHES "${generated_cmakelists_pattern}")
74            set(CATKIN_NONHOMOGENEOUS_WORKSPACE TRUE)
75            message("WARNING: The CMakeLists.txt of the metapackage '${name}' contains non standard content. Use the content of the following file instead: ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/metapackages/${name}/CMakeLists.txt")
76          endif()
77        else()
78          message("WARNING: The metapackage '${name}' has no CMakeLists.txt. Please add one to the package source. You can use the following file: ${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/metapackages/${name}/CMakeLists.txt")
79        endif()
80      else()
81        if(${build_type} MATCHES catkin)
82          message(STATUS "~~  - ${name}")
83        else()
84          set(CATKIN_NONHOMOGENEOUS_WORKSPACE TRUE)
85          if(${build_type} MATCHES cmake)
86            message(STATUS "~~  - ${name} (plain cmake)")
87          else()
88            message(STATUS "~~  - ${name} (unknown)")
89            message(WARNING "Unknown build type '${build_type}' for package '${name}'")
90          endif()
91        endif()
92      endif()
93    endforeach()
94    message(STATUS "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
95
96    if(${CATKIN_NONCONFORMANT_METAPACKAGE})
97      message(FATAL_ERROR "This workspace contains metapackages with a non-standard CMakeLists.txt.")
98    endif()
99    if(${CATKIN_NONHOMOGENEOUS_WORKSPACE})
100      message(FATAL_ERROR "This workspace contains non-catkin packages in it, and catkin cannot build a non-homogeneous workspace without isolation. Try the 'catkin_make_isolated' command instead.")
101    endif()
102
103    foreach(index RANGE ${range})
104      list(GET CATKIN_ORDERED_PACKAGES ${index} name)
105      list(GET CATKIN_ORDERED_PACKAGE_PATHS ${index} path)
106      list(GET CATKIN_ORDERED_PACKAGES_IS_META ${index} is_meta)
107      list(GET CATKIN_ORDERED_PACKAGES_BUILD_TYPE ${index} build_type)
108      if(${is_meta})
109        message(STATUS "+++ processing catkin metapackage: '${name}'")
110        if(EXISTS ${CMAKE_SOURCE_DIR}/${path}/CMakeLists.txt)
111          message(STATUS "==> add_subdirectory(${path})")
112          add_subdirectory(${path})
113        else()
114          message(STATUS "==> add_subdirectory(${path}) (using generated file from <buildspace>/catkin_generated/metapackages/${name})")
115          message("WARNING: Add a CMakeLists.txt file to the metapackage '${name}'")
116          add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/catkin_generated/metapackages/${name} ${CMAKE_BINARY_DIR}/${path})
117        endif()
118      elseif(${build_type} MATCHES catkin)
119        message(STATUS "+++ processing catkin package: '${name}'")
120        message(STATUS "==> add_subdirectory(${path})")
121        add_subdirectory(${path})
122      else()
123        message(FATAL_ERROR "Non-catkin package found, non-homogeneous workspaces are not supported.")
124      endif()
125    endforeach()
126  endif()
127endfunction()
128