| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file Copyright.txt or https://cmake.org/licensing for details. |
| |
| # Scan the Boost headers and determine the library dependencies. Note |
| # that this script only scans one Boost version at once; invoke once |
| # for each Boost release. Note that this does require the headers for |
| # a given component to match the library name, since this computes |
| # inter-library dependencies. Library components for which this |
| # assumption does not hold true and which have dependencies on other |
| # Boost libraries will require special-casing. It also doesn't handle |
| # private dependencies not described in the headers, for static |
| # library dependencies--this is also a limitation of auto-linking, and |
| # I'm unaware of any specific instances where this would be |
| # problematic. |
| # |
| # Invoke in script mode, defining these variables: |
| # BOOST_DIR - the root of the boost includes |
| # |
| # The script will process each directory under the root as a |
| # "component". For each component, all the headers will be scanned to |
| # determine the components it depends upon by following all the |
| # possible includes from this component. This is to match the |
| # behavior of autolinking. |
| |
| # Written by Roger Leigh <rleigh@codelibre.net> |
| |
| # Determine header dependencies on libraries using the embedded dependency information. |
| # |
| # component - the component to check (uses all headers from boost/${component}) |
| # includedir - the path to the Boost headers |
| # _ret_libs - list of library dependencies |
| # |
| function(_Boost_FIND_COMPONENT_DEPENDENCIES component includedir _ret_libs) |
| # _boost_unprocessed_headers - list of headers requiring parsing |
| # _boost_processed_headers - headers already parsed (or currently being parsed) |
| # _boost_new_headers - new headers discovered for future processing |
| |
| set(library_component FALSE) |
| |
| # Start by finding all headers for the component; header |
| # dependencies via #include will be solved by future passes |
| file(GLOB_RECURSE _boost_mpi_python_headers |
| RELATIVE "${includedir}" |
| "${includedir}/boost/mpi/python/*") |
| list(INSERT _boost_mpi_python_headers 0 "boost/mpi/python.hpp") |
| |
| file(GLOB_RECURSE _boost_python_numpy_headers |
| RELATIVE "${includedir}" |
| "${includedir}/boost/python/numpy/*") |
| list(INSERT _boost_python_numpy_headers 0 "boost/python/numpy.hpp") |
| |
| # Special-case since it is part of mpi; look only in boost/mpi/python* |
| if(component STREQUAL "mpi_python") |
| set(_boost_DEPS "python\${component_python_version}") |
| set(library_component TRUE) |
| set(_boost_unprocessed_headers ${_boost_mpi_python_headers}) |
| # Special-case since it is part of python; look only in boost/python/numpy* |
| elseif(component STREQUAL "numpy") |
| set(_boost_DEPS "python\${component_python_version}") |
| set(library_component TRUE) |
| set(_boost_unprocessed_headers ${_boost_python_numpy_headers}) |
| # Special-case since it is a serialization variant; look in boost/serialization |
| elseif(component STREQUAL "wserialization") |
| set(library_component TRUE) |
| file(GLOB_RECURSE _boost_unprocessed_headers |
| RELATIVE "${includedir}" |
| "${includedir}/boost/serialization/*") |
| list(INSERT _boost_unprocessed_headers 0 "boost/serialization.hpp") |
| # Not really a library in its own right, but treat it as one |
| elseif(component STREQUAL "math") |
| set(library_component TRUE) |
| file(GLOB_RECURSE _boost_unprocessed_headers |
| RELATIVE "${includedir}" |
| "${includedir}/boost/math/*") |
| list(INSERT _boost_unprocessed_headers 0 "boost/math.hpp") |
| # Single test header |
| elseif(component STREQUAL "unit_test_framework") |
| set(library_component TRUE) |
| set(_boost_unprocessed_headers "${BOOST_DIR}/test/unit_test.hpp") |
| # Single test header |
| elseif(component STREQUAL "prg_exec_monitor") |
| set(library_component TRUE) |
| set(_boost_unprocessed_headers "${BOOST_DIR}/test/prg_exec_monitor.hpp") |
| # Single test header |
| elseif(component STREQUAL "test_exec_monitor") |
| set(library_component TRUE) |
| set(_boost_unprocessed_headers "${BOOST_DIR}/test/test_exec_monitor.hpp") |
| else() |
| # Default behavior where header directory is the same as the library name. |
| file(GLOB_RECURSE _boost_unprocessed_headers |
| RELATIVE "${includedir}" |
| "${includedir}/boost/${component}/*") |
| list(INSERT _boost_unprocessed_headers 0 "boost/${component}.hpp") |
| list(REMOVE_ITEM _boost_unprocessed_headers ${_boost_mpi_python_headers} ${_boost_python_numpy_headers}) |
| endif() |
| |
| while(_boost_unprocessed_headers) |
| list(APPEND _boost_processed_headers ${_boost_unprocessed_headers}) |
| foreach(header ${_boost_unprocessed_headers}) |
| if(EXISTS "${includedir}/${header}") |
| file(STRINGS "${includedir}/${header}" _boost_header_includes REGEX "^#[ \t]*include[ \t]*<boost/[^>][^>]*>") |
| # The optional whitespace before "#" is intentional |
| # (boost/serialization/config.hpp bug). |
| file(STRINGS "${includedir}/${header}" _boost_header_deps REGEX "^[ \t]*#[ \t]*define[ \t][ \t]*BOOST_LIB_NAME[ \t][ \t]*boost_") |
| |
| foreach(line ${_boost_header_includes}) |
| string(REGEX REPLACE "^#[ \t]*include[ \t]*<(boost/[^>][^>]*)>.*" "\\1" _boost_header_match "${line}") |
| list(FIND _boost_processed_headers "${_boost_header_match}" _boost_header_processed) |
| list(FIND _boost_new_headers "${_boost_header_match}" _boost_header_new) |
| if (_boost_header_processed EQUAL -1 AND _boost_header_new EQUAL -1) |
| list(APPEND _boost_new_headers ${_boost_header_match}) |
| endif() |
| endforeach() |
| |
| foreach(line ${_boost_header_deps}) |
| string(REGEX REPLACE "^[ \t]*#[ \t]*define[ \t][ \t]*BOOST_LIB_NAME[ \t][ \t]*boost_([^ \t][^ \t]*).*" "\\1" _boost_component_match "${line}") |
| string(REPLACE "python3" "python" _boost_component_match "${_boost_component_match}") |
| string(REPLACE "numpy3" "numpy" _boost_component_match "${_boost_component_match}") |
| list(FIND _boost_DEPS "${_boost_component_match}" _boost_dep_found) |
| if(_boost_component_match STREQUAL "bzip2" OR |
| _boost_component_match STREQUAL "zlib") |
| # These components may or may not be required; not |
| # possible to tell without knowing where and when |
| # BOOST_BZIP2_BINARY and BOOST_ZLIB_BINARY are defined. |
| # If building against an external zlib or bzip2, this is |
| # undesirable. |
| continue() |
| endif() |
| if(component STREQUAL "mpi" AND |
| (_boost_component_match STREQUAL "mpi_python" OR |
| _boost_component_match STREQUAL "python")) |
| # Optional python dependency; skip to avoid making it a |
| # hard dependency (handle as special-case for mpi_python). |
| continue() |
| endif() |
| if(component STREQUAL "python" AND |
| _boost_component_match STREQUAL "numpy") |
| # Optional python dependency; skip to avoid making it a |
| # hard dependency (handle as special-case for numpy). |
| continue() |
| endif() |
| if(component STREQUAL "nowide" AND |
| _boost_component_match STREQUAL "filesystem") |
| # Optional filesystem dependency; skip to avoid making it a |
| # hard dependency. |
| continue() |
| endif() |
| if (_boost_dep_found EQUAL -1 AND |
| NOT "${_boost_component_match}" STREQUAL "${component}") |
| list(APPEND _boost_DEPS "${_boost_component_match}") |
| endif() |
| if("${_boost_component_match}" STREQUAL "${component}") |
| set(library_component TRUE) |
| endif() |
| endforeach() |
| endif() |
| endforeach() |
| set(_boost_unprocessed_headers ${_boost_new_headers}) |
| unset(_boost_new_headers) |
| endwhile() |
| |
| # message(STATUS "Unfiltered dependencies for Boost::${component}: ${_boost_DEPS}") |
| |
| if(NOT library_component) |
| unset(_boost_DEPS) |
| endif() |
| set(${_ret_libs} ${_boost_DEPS} PARENT_SCOPE) |
| |
| #string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_boost_DEPS}") |
| #if (NOT _boost_DEPS_STRING) |
| # set(_boost_DEPS_STRING "(none)") |
| #endif() |
| #message(STATUS "Dependencies for Boost::${component}: ${_boost_DEPS_STRING}") |
| endfunction() |
| |
| |
| message(STATUS "Scanning ${BOOST_DIR}") |
| |
| # List of all directories and files |
| file(GLOB boost_contents RELATIVE "${BOOST_DIR}/boost" "${BOOST_DIR}/boost/*") |
| |
| # Components as directories |
| foreach(component ${boost_contents}) |
| if(IS_DIRECTORY "${BOOST_DIR}/boost/${component}") |
| list(APPEND boost_components "${component}") |
| endif() |
| endforeach() |
| |
| # The following components are not top-level directories, so require |
| # special-casing: |
| |
| # Special-case mpi_python, since it's a part of mpi |
| if(IS_DIRECTORY "${BOOST_DIR}/boost/mpi" AND |
| IS_DIRECTORY "${BOOST_DIR}/boost/python") |
| list(APPEND boost_components "mpi_python") |
| endif() |
| # Special-case numpy, since it's a part of python |
| if(IS_DIRECTORY "${BOOST_DIR}/boost/python" AND |
| IS_DIRECTORY "${BOOST_DIR}/boost/python/numpy") |
| list(APPEND boost_components "numpy") |
| endif() |
| # Special-case wserialization, which is a variant of serialization |
| if(IS_DIRECTORY "${BOOST_DIR}/boost/serialization") |
| list(APPEND boost_components "wserialization") |
| endif() |
| # Special-case math* since there are six libraries, but no actual math |
| # library component. Handle specially when scanning above. |
| # |
| # Special-case separate test libraries, which are all part of test |
| if(EXISTS "${BOOST_DIR}/test/unit_test.hpp") |
| list(APPEND boost_components "unit_test_framework") |
| endif() |
| if(EXISTS "${BOOST_DIR}/test/prg_exec_monitor.hpp") |
| list(APPEND boost_components "prg_exec_monitor") |
| endif() |
| if(EXISTS "${BOOST_DIR}/test/test_exec_monitor.hpp") |
| list(APPEND boost_components "test_exec_monitor") |
| endif() |
| |
| if(boost_components) |
| list(SORT boost_components) |
| endif() |
| |
| # Process each component defined above |
| foreach(component ${boost_components}) |
| string(TOUPPER ${component} UPPERCOMPONENT) |
| _Boost_FIND_COMPONENT_DEPENDENCIES("${component}" "${BOOST_DIR}" |
| _Boost_${UPPERCOMPONENT}_LIBRARY_DEPENDENCIES) |
| endforeach() |
| |
| # Output results |
| foreach(component ${boost_components}) |
| string(TOUPPER ${component} UPPERCOMPONENT) |
| if(_Boost_${UPPERCOMPONENT}_LIBRARY_DEPENDENCIES) |
| string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_Boost_${UPPERCOMPONENT}_LIBRARY_DEPENDENCIES}") |
| message(STATUS "set(_Boost_${UPPERCOMPONENT}_DEPENDENCIES ${_boost_DEPS_STRING})") |
| endif() |
| endforeach() |