You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
790 lines
29 KiB
790 lines
29 KiB
# @HEADER
|
|
# ************************************************************************
|
|
#
|
|
# TriBITS: Tribal Build, Integrate, and Test System
|
|
# Copyright 2013 Sandia Corporation
|
|
#
|
|
# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
# the U.S. Government retains certain rights in this software.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# 3. Neither the name of the Corporation nor the names of the
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
|
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
# ************************************************************************
|
|
# @HEADER
|
|
|
|
include_guard()
|
|
|
|
include(TribitsExternalPackageWriteConfigFile)
|
|
|
|
include(AdvancedSet)
|
|
include(AppendSet)
|
|
include(AssertDefined)
|
|
include(DualScopeSet)
|
|
include(GlobalNullSet)
|
|
include(GlobalSet)
|
|
include(MultilineSet)
|
|
include(CMakeParseArguments)
|
|
include(SetNotFound)
|
|
include(Split)
|
|
|
|
|
|
# @FUNCTION: tribits_tpl_allow_pre_find_package()
|
|
#
|
|
# Function that determines if a TriBITS find module file
|
|
# ``FindTPL<tplName>.cmake`` is allowed to call ``find_package(<tplName>
|
|
# ...)`` before calling `tribits_tpl_find_include_dirs_and_libraries()`_.
|
|
#
|
|
# Usage::
|
|
#
|
|
# tribits_tpl_allow_pre_find_package( <tplName>
|
|
# <allowPackagePrefindOut> )
|
|
#
|
|
# The required arguments are:
|
|
#
|
|
# ``<tplName>`` : The input name of the TriBITS TPL (e.g. ``HDF5``).
|
|
#
|
|
# ``<allowPackagePrefindOut>`` : Name of a variable which will be set to
|
|
# ``TRUE`` on output if ``find_package(<tplName> ...)`` should be called to
|
|
# find the TPL ``<tplName>`` or ``FALSE`` if it should not be called.
|
|
#
|
|
# This function will set ``<allowPackagePrefindOut>`` to ``FALSE`` if any of
|
|
# the variables ``TPL_<tplName>_INCLUDE_DIRS``, ``${TPL_<tplName>_LIBRARIES``,
|
|
# or ``TPL_<tplName>_LIBRARY_DIRS`` are set. This allows the user to override
|
|
# the search for the library components and just specify the absolute
|
|
# locations. The function will also set ``<allowPackagePrefindOut>`` to
|
|
# ``FALSE`` if ``<tplName>_INCLUDE_DIRS``, ``<tplName>_LIBRARY_NAMES``, or
|
|
# ``<tplName>_LIBRARY_DIRS`` is set and ``<tplName>_FORCE_PRE_FIND_PACKAGE``
|
|
# is set to ``FALSE``. Otherwise, if ``<tplName>_FORCE_PRE_FIND_PACKAGE`` is
|
|
# set to ``TRUE``, the function will not return ``FALSE`` for
|
|
# ``<allowPackagePrefindOut>`` no matter what the values of
|
|
# ``<tplName>_INCLUDE_DIRS``, ``<tplName>_LIBRARY_NAMES``, or
|
|
# ``<tplName>_LIBRARY_DIRS``. Finally, ``<allowPackagePrefindOut>`` is set to
|
|
# ``FALSE`` if ``<tplName>_ALLOW_PACKAGE_PREFIND=OFF`` is set in the cache.
|
|
#
|
|
# The variable ``<tplName>_FORCE_PRE_FIND_PACKAGE`` is needed to allow users
|
|
# (or the ``FindTPL<tplName>.cmake`` module itself) to avoid name clashes with
|
|
# the variables ``<tplName>_INCLUDE_DIRS`` or ``<tplName>_LIBRARY_DIRS`` in
|
|
# the usage of ``find_package(<tplName> ...)`` because a lot of default
|
|
# ``Find<tplName>.cmake`` modules also use these variables. This function
|
|
# sets ``<tplName>_FORCE_PRE_FIND_PACKAGE`` as a cache variable with default
|
|
# value ``FALSE`` to maintain backward compatibility with existing
|
|
# ``FindTPL<tplName>.cmake`` modules.
|
|
#
|
|
# The cache variable ``<tplName>_ALLOW_PACKAGE_PREFIND`` is to allow the user
|
|
# to disable the prefind call to ``find_package()`` even if it would be
|
|
# allowed otherwise.
|
|
#
|
|
# See `Creating FindTPL<tplName>.cmake using find_package() without IMPORTED
|
|
# targets`_ for details in how to use this function to create a
|
|
# ``FindTPL<tplName>.cmake`` module file.
|
|
#
|
|
function(tribits_tpl_allow_pre_find_package TPL_NAME ALLOW_PACKAGE_PREFIND_OUT)
|
|
|
|
if (TRIBITS_TPL_ALLOW_PRE_FIND_PACKAGE_DEBUG)
|
|
message("TRIBITS_TPL_ALLOW_PRE_FIND_PACKAGE: '${TPL_NAME}' '${ALLOW_PACKAGE_PREFIND_OUT}'")
|
|
print_var(${TPL_NAME}_INCLUDE_DIRS)
|
|
print_var(${TPL_NAME}_LIBRARY_NAMES)
|
|
print_var(${TPL_NAME}_LIBRARY_DIRS)
|
|
print_var(${TPL_NAME}_FORCE_PRE_FIND_PACKAGE)
|
|
endif()
|
|
|
|
advanced_set(${TPL_NAME}_FORCE_PRE_FIND_PACKAGE FALSE
|
|
CACHE BOOL
|
|
"Determines if the variables ${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] should be ignored and the pre-find find_package(${TPL_NAME} should be performed anyway. But this will *not* do the pre-find if any of the TPL_${TPL_NAME}_[INCLUDE_DIRS,LIBRARY_NAMES,LIBRARY_DIRS] vars are set." )
|
|
|
|
# Start out with TRUE and set to FALSE in logic below
|
|
set(${TPL_NAME}_ALLOW_PACKAGE_PREFIND TRUE CACHE BOOL
|
|
"Set to FALSE to skip find_package() prefind for the TriBITS TPL '${TPL_NAME}'")
|
|
|
|
# Start out with TRUE and set to FALSE in logic below
|
|
set(ALLOW_PACKAGE_PREFIND TRUE)
|
|
|
|
if (NOT ${TPL_NAME}_ALLOW_PACKAGE_PREFIND)
|
|
set(ALLOW_PACKAGE_PREFIND FALSE)
|
|
elseif (
|
|
(NOT "${TPL_${TPL_NAME}_INCLUDE_DIRS}" STREQUAL "")
|
|
OR (NOT "${TPL_${TPL_NAME}_LIBRARIES}" STREQUAL "")
|
|
OR (NOT "${TPL_${TPL_NAME}_LIBRARY_DIRS}" STREQUAL "")
|
|
)
|
|
# The user has selected one or more of the final vars so skip calling
|
|
# find_package(${TPL_NAME} ...) ...
|
|
set(ALLOW_PACKAGE_PREFIND FALSE)
|
|
elseif (
|
|
(NOT "${${TPL_NAME}_INCLUDE_DIRS}" STREQUAL "")
|
|
OR (NOT "${${TPL_NAME}_LIBRARY_NAMES}" STREQUAL "")
|
|
OR (NOT "${${TPL_NAME}_LIBRARY_DIRS}" STREQUAL "")
|
|
)
|
|
# One or more of the ${TPL_NAME}_XXX variables are set
|
|
if (${TPL_NAME}_FORCE_PRE_FIND_PACKAGE)
|
|
# Even with one or more of the ${TPL_NAME}_XXX vars set, we still want
|
|
# to do the find_package(${TPL_NAME} ...) search and ignore this
|
|
# override.
|
|
else()
|
|
# We will not ignore the override of these variables and will instead go
|
|
# ahead and skip the pre-find.
|
|
set(ALLOW_PACKAGE_PREFIND FALSE)
|
|
endif()
|
|
endif()
|
|
|
|
set(${ALLOW_PACKAGE_PREFIND_OUT} ${ALLOW_PACKAGE_PREFIND} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
|
|
# @FUNCTION: tribits_tpl_find_include_dirs_and_libraries()
|
|
#
|
|
# This function reads (cache) variables that specify where to find a `TriBITS
|
|
# TPL`_'s headers and libraries and then creates IMPORTED targets, the
|
|
# ``<tplName>::all_libs`` target, and writes the file
|
|
# ``<tplName>Config.cmake`` into the standard location in the build directory.
|
|
# This function is typically called inside of a ``FindTPL<tplName>.cmake``
|
|
# module file (see `${TPL_NAME}_FINDMOD`_).
|
|
#
|
|
# Usage::
|
|
#
|
|
# tribits_tpl_find_include_dirs_and_libraries(
|
|
# <tplName>
|
|
# [REQUIRED_HEADERS <header1> <header2> ...]
|
|
# [MUST_FIND_ALL_HEADERS]
|
|
# [REQUIRED_LIBS_NAMES <libname1> <libname2> ...]
|
|
# [MUST_FIND_ALL_LIBS]
|
|
# [NO_PRINT_ENABLE_SUCCESS_FAIL]
|
|
# )
|
|
#
|
|
# This function can be called to specify/require header files and include
|
|
# directories and/or a list of libraries.
|
|
#
|
|
# The input arguments to this function are:
|
|
#
|
|
# ``<tplName>``
|
|
#
|
|
# Name of the TPL that is listed in a `<repoDir>/TPLsList.cmake`_ file.
|
|
#
|
|
# ``REQUIRED_HEADERS``
|
|
#
|
|
# List of header files that are searched in order to find the TPL's
|
|
# include directories files using ``find_path()``.
|
|
#
|
|
# ``MUST_FIND_ALL_HEADERS``
|
|
#
|
|
# If set, then all of the header files listed in ``REQUIRED_HEADERS`` must
|
|
# be found (unless ``TPL_<tplName>_INCLUDE_DIRS`` is already set).
|
|
#
|
|
# ``REQUIRED_LIBS_NAMES``
|
|
#
|
|
# List of libraries that are searched for when looking for the TPL's
|
|
# libraries using ``find_library()``. This list can be overridden by the
|
|
# user by setting ``<tplName>_LIBRARY_NAMES`` (see below).
|
|
#
|
|
# ``MUST_FIND_ALL_LIBS``
|
|
#
|
|
# If set, then all of the library files listed in ``REQUIRED_LIBS_NAMES``
|
|
# must be found or the TPL is considered not found (unless
|
|
# ``TPL_<tplName>_LIBRARIES`` is already set). If the global cache var
|
|
# ``<Project>_MUST_FIND_ALL_TPL_LIBS`` is set to ``TRUE``, then this is
|
|
# turned on as well. WARNING: The default is not to require finding all
|
|
# of the listed libs. (This is to maintain backward compatibility with
|
|
# some older ``FindTPL<tplName>.cmake`` modules.)
|
|
#
|
|
# ``NO_PRINT_ENABLE_SUCCESS_FAIL``
|
|
#
|
|
# If set, then the final success/fail will not be printed
|
|
#
|
|
# This function implements the TPL find behavior described in `Enabling
|
|
# support for an optional Third-Party Library (TPL)`_.
|
|
#
|
|
# The following (cache) variables, if set, will be used by this function:
|
|
#
|
|
# ``<tplName>_INCLUDE_DIRS`` (type ``PATH``)
|
|
#
|
|
# List of paths to search first for header files defined in
|
|
# ``REQUIRED_HEADERS <header1> <header2> ...``.
|
|
#
|
|
# ``<tplName>_LIBRARY_DIRS`` (type ``PATH``)
|
|
#
|
|
# The list of directories to search first for libraries defined in
|
|
# ``REQUIRED_LIBS_NAMES <libname1> <libname2> ...``. If, for some reason,
|
|
# no libraries should be linked in for this particular configuration, then
|
|
# setting ``<tplName>_LIBRARY_DIRS=OFF`` or is empty will no special paths
|
|
# will be searched.
|
|
#
|
|
# ``<tplName>_LIBRARY_NAMES`` (type ``STRING``)
|
|
#
|
|
# List of library names to be looked for instead of what is specified in
|
|
# ``REQUIRED_LIBS_NAMES <libname1> <libname2> ...``.
|
|
#
|
|
# ``<tplName>_LIB_ENABLED_DEPENDENCIES``
|
|
#
|
|
# List of direct upstream external package/TPL dependencies that also
|
|
# define ``<upstreamTplName>::all_libs`` targets.
|
|
#
|
|
# An addition, the function will avoid calling the find operations if the
|
|
# following (cache) variables are set on input:
|
|
#
|
|
# ``TPL_<tplName>_INCLUDE_DIRS`` (type ``PATH``)
|
|
#
|
|
# A list of common-separated full directory paths that contain the TPL's
|
|
# header files.
|
|
#
|
|
# ``TPL_<tplName>_LIBRARIES`` (type ``FILEPATH``)
|
|
#
|
|
# A list of commons-separated full library names (i.e. output from
|
|
# ``find_library()``) for all of the libraries for the TPL.
|
|
#
|
|
# This function produces the following:
|
|
#
|
|
# ``TPL_<tplName>_NOT_FOUND`` (type ``BOOL``)
|
|
#
|
|
# Will be set to ``ON`` if all of the parts of the TPL could not be found.
|
|
#
|
|
# ``<tplName>::<libname>``
|
|
#
|
|
# Namespaced IMPORTED target for every library found or specified in
|
|
# ``TPL_<tplName>_LIBRARIES``. These IMPORTED targets will have the
|
|
# ``<upstreamTplName>::all_libs`` for the upstream external packages/TPLs
|
|
# listed in ``<tplName>_LIB_ENABLED_DEPENDENCIES``.
|
|
#
|
|
# ``<tplName>::all_libs``
|
|
#
|
|
# INTERFACE target that depends on all of the created IMPORTED targets.
|
|
#
|
|
# ``<buildDir>/external_packages/<tplName>/<tplName>Config.cmake``
|
|
#
|
|
# A package configure file that contains all of the generated IMPORTED
|
|
# targets ``<tplName>::<libname>`` and the ``<tplName>::all_libs`` target.
|
|
# This fill will also call ``find_dependency()`` to pull in
|
|
# ``<upstreamTplName>Config.cmake`` files for upstream TPLs that are
|
|
# listed in ``<tplName>_LIB_ENABLED_DEPENDENCIES``. (For more
|
|
# information, see `tribits_extpkg_write_config_file()`_.)
|
|
#
|
|
# Note, if ``TPL_TENTATIVE_ENABLE_<tplName>=ON``, then if all of the parts of
|
|
# the TPL can't be found, then ``TPL_ENABLE_<tplName>`` will be (forced) set
|
|
# to ``OFF`` in the cache. See `tribits_tpl_tentatively_enable()`_.
|
|
#
|
|
function(tribits_tpl_find_include_dirs_and_libraries TPL_NAME)
|
|
|
|
# Make sure the right name is used
|
|
assert_defined(TPL_ENABLE_${TPL_NAME})
|
|
|
|
cmake_parse_arguments(
|
|
#prefix
|
|
PARSE
|
|
#options
|
|
"MUST_FIND_ALL_LIBS;MUST_FIND_ALL_HEADERS;NO_PRINT_ENABLE_SUCCESS_FAIL"
|
|
#one_value_keywords
|
|
""
|
|
#multi_value_keywords
|
|
"REQUIRED_HEADERS;REQUIRED_LIBS_NAMES"
|
|
${ARGN}
|
|
)
|
|
|
|
tribits_check_for_unparsed_arguments()
|
|
|
|
if (${PROJECT_NAME}_VERBOSE_CONFIGURE)
|
|
set(TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE TRUE)
|
|
endif()
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
message("TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES: ${TPL_NAME}")
|
|
print_var(PARSE_REQUIRED_HEADERS)
|
|
print_var(PARSE_REQUIRED_LIBS_NAMES)
|
|
print_var(TPL_${TPL_NAME}_INCLUDE_DIRS)
|
|
print_var(TPL_${TPL_NAME}_LIBRARIES)
|
|
endif()
|
|
|
|
if (TPL_TENTATIVE_ENABLE_${TPL_NAME})
|
|
message("-- Attempting to tentatively enable TPL '${TPL_NAME}' ...")
|
|
set(ERROR_MSG_MODE)
|
|
else()
|
|
set(ERROR_MSG_MODE SEND_ERROR)
|
|
endif()
|
|
|
|
# Allow user override for finding libraries even if REQUIRED_LIBS_NAMES is
|
|
# empty on input
|
|
|
|
multiline_set(DOCSTR
|
|
"List of semi-colon separated names of libraries needed to link to for"
|
|
" the TPL ${TPL_NAME}. This list of libraries will be search for in"
|
|
" find_library(...) calls along with the directories specified with"
|
|
" ${TPL_NAME}_LIBRARY_DIRS. NOTE: This is not the final list of libraries"
|
|
" used for linking. That is specified by TPL_${TPL_NAME}_LIBRARIES!"
|
|
)
|
|
advanced_set(${TPL_NAME}_LIBRARY_NAMES ${PARSE_REQUIRED_LIBS_NAMES}
|
|
CACHE STRING ${DOCSTR})
|
|
split("${${TPL_NAME}_LIBRARY_NAMES}" "," ${TPL_NAME}_LIBRARY_NAMES)
|
|
print_var(${TPL_NAME}_LIBRARY_NAMES)
|
|
|
|
# Let the user override what the names of the libraries which might
|
|
# actually mean that no libraries are searched for.
|
|
set(REQUIRED_LIBS_NAMES ${${TPL_NAME}_LIBRARY_NAMES})
|
|
|
|
#
|
|
# User options
|
|
#
|
|
|
|
if (REQUIRED_LIBS_NAMES)
|
|
|
|
# Library directories
|
|
|
|
multiline_set(DOCSTR
|
|
"List of semi-colon separated paths to look for the TPL ${TPL_NAME}"
|
|
" libraries. This list of paths will be passed into a find_library(...)"
|
|
" command to find the libraries listed in ${TPL_NAME}_LIBRARY_NAMES."
|
|
" Note that this set of paths is also the default value used for"
|
|
" ${TPL_NAME}_LIBRARY_DIRS. Therefore, if the headers exist in the"
|
|
" same directories as the library, you do not need to set"
|
|
" ${TPL_NAME}_LIBRARY_DIRS."
|
|
)
|
|
|
|
advanced_set(${TPL_NAME}_LIBRARY_DIRS "" CACHE PATH ${DOCSTR})
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(${TPL_NAME}_LIBRARY_DIRS)
|
|
endif()
|
|
|
|
# Libraries
|
|
|
|
if (${PROJECT_NAME}_MUST_FIND_ALL_TPL_LIBS)
|
|
set(MUST_FIND_ALL_LIBS TRUE)
|
|
else()
|
|
set(MUST_FIND_ALL_LIBS ${PARSE_MUST_FIND_ALL_LIBS})
|
|
endif()
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(${TPL_NAME}_LIBRARY_NAMES)
|
|
print_var(REQUIRED_LIBS_NAMES)
|
|
endif()
|
|
|
|
else()
|
|
|
|
set(${TPL_NAME}_LIBRARY_DIRS "") # Just to ignore below!
|
|
|
|
endif()
|
|
|
|
# Include directories
|
|
|
|
if (PARSE_REQUIRED_HEADERS)
|
|
|
|
multiline_set(DOCSTR
|
|
"List of semi-colon separated paths to look for the TPL ${TPL_NAME}"
|
|
" headers. This list of paths will be passed into a find_path(...)"
|
|
" command to find the headers for ${TPL_NAME} (which are known in advance)."
|
|
)
|
|
advanced_set(${TPL_NAME}_INCLUDE_DIRS ${${TPL_NAME}_LIBRARY_DIRS}
|
|
CACHE PATH ${DOCSTR})
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(${TPL_NAME}_LIBRARY_DIRS)
|
|
print_var(${TPL_NAME}_INCLUDE_DIRS)
|
|
print_var(PARSE_REQUIRED_HEADERS)
|
|
endif()
|
|
|
|
endif()
|
|
|
|
#
|
|
# Set the lib extensions to find
|
|
#
|
|
|
|
# Save the default the first time through
|
|
if (NOT CMAKE_FIND_LIBRARY_SUFFIXES_DEFAULT)
|
|
set(TPL_CMAKE_FIND_LIBRARY_SUFFIXES_DEFAULT ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
|
#print_var(TPL_CMAKE_FIND_LIBRARY_SUFFIXES_DEFAULT)
|
|
endif()
|
|
|
|
#print_var(TPL_FIND_SHARED_LIBS)
|
|
#print_var(CMAKE_FIND_LIBRARY_SUFFIXES)
|
|
# Set libraries to find
|
|
if (TPL_FIND_SHARED_LIBS)
|
|
# The default should be to find shared libs first
|
|
set(TPL_CMAKE_FIND_LIBRARY_SUFFIXES ${TPL_CMAKE_FIND_LIBRARY_SUFFIXES_DEFAULT})
|
|
else()
|
|
if (WIN32)
|
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a)
|
|
else()
|
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
|
|
endif()
|
|
endif()
|
|
#print_var(CMAKE_FIND_LIBRARY_SUFFIXES)
|
|
|
|
#
|
|
# Direct build options
|
|
#
|
|
|
|
set(_${TPL_NAME}_ENABLE_SUCCESS TRUE)
|
|
|
|
if (REQUIRED_LIBS_NAMES)
|
|
|
|
# Libraries
|
|
|
|
if (MUST_FIND_ALL_LIBS)
|
|
set(LIB_NOT_FOUND_MSG_PREFIX "ERROR:")
|
|
else()
|
|
set(LIB_NOT_FOUND_MSG_PREFIX "NOTE:")
|
|
endif()
|
|
|
|
if (NOT TPL_${TPL_NAME}_LIBRARIES)
|
|
|
|
if (MUST_FIND_ALL_LIBS)
|
|
message("-- Must find at least one lib in each of the"
|
|
" lib sets \"${REQUIRED_LIBS_NAMES}\"")
|
|
endif()
|
|
|
|
message( "-- Searching for libs in ${TPL_NAME}_LIBRARY_DIRS='${${TPL_NAME}_LIBRARY_DIRS}'")
|
|
|
|
set(LIBRARIES_FOUND)
|
|
|
|
foreach(LIBNAME_SET ${REQUIRED_LIBS_NAMES})
|
|
|
|
message("-- Searching for a lib in the set \"${LIBNAME_SET}\":")
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(LIBNAME_SET)
|
|
endif()
|
|
|
|
set(LIBNAME_LIST ${LIBNAME_SET})
|
|
separate_arguments(LIBNAME_LIST)
|
|
|
|
set(LIBNAME_SET_LIB)
|
|
|
|
foreach(LIBNAME ${LIBNAME_LIST})
|
|
|
|
message("-- Searching for lib '${LIBNAME}' ...")
|
|
|
|
if (${TPL_NAME}_LIBRARY_DIRS)
|
|
set(PATHS_ARG PATHS ${${TPL_NAME}_LIBRARY_DIRS})
|
|
else()
|
|
set(PATHS_ARG PATHS)
|
|
endif()
|
|
|
|
set_notfound(_${TPL_NAME}_${LIBNAME}_LIBRARY)
|
|
find_library( _${TPL_NAME}_${LIBNAME}_LIBRARY
|
|
NAMES ${LIBNAME}
|
|
${PATHS_ARG} NO_DEFAULT_PATH )
|
|
find_library( _${TPL_NAME}_${LIBNAME}_LIBRARY
|
|
NAMES ${LIBNAME} )
|
|
mark_as_advanced(_${TPL_NAME}_${LIBNAME}_LIBRARY)
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(_${TPL_NAME}_${LIBNAME}_LIBRARY)
|
|
endif()
|
|
|
|
if (_${TPL_NAME}_${LIBNAME}_LIBRARY)
|
|
message("-- Found lib '${_${TPL_NAME}_${LIBNAME}_LIBRARY}'")
|
|
set(LIBNAME_SET_LIB ${_${TPL_NAME}_${LIBNAME}_LIBRARY})
|
|
break()
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
if (NOT LIBNAME_SET_LIB)
|
|
message(
|
|
"-- ${LIB_NOT_FOUND_MSG_PREFIX} Did not find a lib in the lib set \"${LIBNAME_SET}\""
|
|
" for the TPL '${TPL_NAME}'!")
|
|
if (MUST_FIND_ALL_LIBS)
|
|
set(_${TPL_NAME}_ENABLE_SUCCESS FALSE)
|
|
else()
|
|
break()
|
|
endif()
|
|
endif()
|
|
|
|
append_set(LIBRARIES_FOUND ${LIBNAME_SET_LIB})
|
|
|
|
endforeach()
|
|
|
|
multiline_set(DOCSTR
|
|
"List of semi-colon separated full paths to the libraries for the TPL"
|
|
" ${TPL_NAME}. This is the final variable that is used in the link"
|
|
" commands. The user variable ${TPL_NAME}_LIBRARY_DIRS is used to look"
|
|
" for the know library names but but is just a suggestion."
|
|
" This variable, however, is the final value and will not be touched."
|
|
)
|
|
advanced_set( TPL_${TPL_NAME}_LIBRARIES ${LIBRARIES_FOUND}
|
|
CACHE FILEPATH ${DOCSTR} FORCE)
|
|
# Above, we have to force the set in case the find failed the last
|
|
# configure in which case this cache var will be empty. NOTE: If the
|
|
# user specified a non-empty TPL_${TPL_NAME}_LIBRARIES, then we would
|
|
# never get here in the first place!
|
|
|
|
if (NOT TPL_${TPL_NAME}_LIBRARIES OR NOT _${TPL_NAME}_ENABLE_SUCCESS)
|
|
message(
|
|
"-- ERROR: Could not find the libraries for the TPL '${TPL_NAME}'!")
|
|
message(
|
|
"-- TIP: If the TPL '${TPL_NAME}' is on your system then you can set:\n"
|
|
" -D${TPL_NAME}_LIBRARY_DIRS='<dir0>;<dir1>;...'\n"
|
|
" to point to the directories where these libraries may be found.\n"
|
|
" Or, just set:\n"
|
|
" -DTPL_${TPL_NAME}_LIBRARIES='<path-to-libs0>;<path-to-libs1>;...'\n"
|
|
" to point to the full paths for the libraries which will\n"
|
|
" bypass any search for libraries and these libraries will be used without\n"
|
|
" question in the build. (But this will result in a build-time error\n"
|
|
" if not all of the necessary symbols are found.)")
|
|
tribits_tpl_find_include_dirs_and_libraries_handle_fail()
|
|
endif()
|
|
|
|
endif()
|
|
|
|
# Print the final value to be used *always*
|
|
message("-- TPL_${TPL_NAME}_LIBRARIES='${TPL_${TPL_NAME}_LIBRARIES}'")
|
|
|
|
else()
|
|
|
|
# There are no libraries so set the libraries to null but don't
|
|
# change the cache which should not even have this variable in it.
|
|
# This set command is only to follow the standards for the package
|
|
# support CMake code.
|
|
global_null_set(TPL_${TPL_NAME}_LIBRARIES)
|
|
|
|
endif()
|
|
|
|
# Include directories
|
|
|
|
if (PARSE_REQUIRED_HEADERS)
|
|
|
|
if (NOT TPL_${TPL_NAME}_INCLUDE_DIRS)
|
|
|
|
if (PARSE_MUST_FIND_ALL_HEADERS)
|
|
message("-- Must find at least one header in each of the"
|
|
" header sets \"${PARSE_REQUIRED_HEADERS}\"")
|
|
endif()
|
|
|
|
message( "-- Searching for headers in ${TPL_NAME}_INCLUDE_DIRS='${${TPL_NAME}_INCLUDE_DIRS}'")
|
|
|
|
foreach(INCLUDE_FILE_SET ${PARSE_REQUIRED_HEADERS})
|
|
|
|
message("-- Searching for a header file in the set \"${INCLUDE_FILE_SET}\":")
|
|
|
|
set(INCLUDE_FILE_LIST ${INCLUDE_FILE_SET})
|
|
separate_arguments(INCLUDE_FILE_LIST)
|
|
set(INCLUDE_FILE_SET_PATH) # Start out as empty list
|
|
|
|
foreach(INCLUDE_FILE ${INCLUDE_FILE_LIST})
|
|
|
|
message("-- Searching for header '${INCLUDE_FILE}' ...")
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(INCLUDE_FILE)
|
|
endif()
|
|
|
|
set_notfound(_${TPL_NAME}_${INCLUDE_FILE}_PATH)
|
|
find_path( _${TPL_NAME}_${INCLUDE_FILE}_PATH
|
|
NAMES ${INCLUDE_FILE}
|
|
PATHS ${${TPL_NAME}_INCLUDE_DIRS}
|
|
NO_DEFAULT_PATH)
|
|
find_path( _${TPL_NAME}_${INCLUDE_FILE}_PATH
|
|
NAMES ${INCLUDE_FILE} )
|
|
mark_as_advanced(_${TPL_NAME}_${INCLUDE_FILE}_PATH)
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(_${TPL_NAME}_${INCLUDE_FILE}_PATH)
|
|
endif()
|
|
|
|
if(_${TPL_NAME}_${INCLUDE_FILE}_PATH)
|
|
message( "-- Found header '${_${TPL_NAME}_${INCLUDE_FILE}_PATH}/${INCLUDE_FILE}'")
|
|
append_set(INCLUDE_FILE_SET_PATH ${_${TPL_NAME}_${INCLUDE_FILE}_PATH})
|
|
break()
|
|
endif()
|
|
|
|
endforeach()
|
|
|
|
if(NOT INCLUDE_FILE_SET_PATH)
|
|
message("-- ERROR: Could not find a header file in"
|
|
" the set \"${INCLUDE_FILE_SET}\"")
|
|
if(PARSE_MUST_FIND_ALL_HEADERS)
|
|
set(_${TPL_NAME}_ENABLE_SUCCESS FALSE)
|
|
endif()
|
|
endif()
|
|
|
|
append_set(INCLUDES_FOUND ${INCLUDE_FILE_SET_PATH})
|
|
|
|
endforeach(INCLUDE_FILE_SET ${PARSE_REQUIRED_HEADERS})
|
|
|
|
if (INCLUDES_FOUND)
|
|
list(REMOVE_DUPLICATES INCLUDES_FOUND)
|
|
endif()
|
|
|
|
multiline_set(DOCSTR
|
|
"List of semi-colon separated paths to append to the compile invocations"
|
|
" to find the headers for the TPL ${TPL_NAME}. This is the final variable"
|
|
" that is used in the build commands. The user variable ${TPL_NAME}_INCLUDE_DIRS"
|
|
" is used to look for the given headers first but is just a suggestion."
|
|
" This variable, however, is the final value and will not be touched."
|
|
)
|
|
|
|
advanced_set(TPL_${TPL_NAME}_INCLUDE_DIRS ${INCLUDES_FOUND}
|
|
CACHE PATH ${DOCSTR} FORCE)
|
|
# Above, we have to force the set in case the find failed the last
|
|
# configure in which case this cache var will be empty. NOTE: If the
|
|
# user specified a non-empty TPL_${TPL_NAME}_INCLUDE_DIRS, then we would
|
|
# never get here in the first place!
|
|
|
|
if (NOT TPL_${TPL_NAME}_INCLUDE_DIRS OR NOT _${TPL_NAME}_ENABLE_SUCCESS)
|
|
message(
|
|
"-- ERROR: Could not find the include directories for TPL '${TPL_NAME}'!")
|
|
message(
|
|
"-- TIP: If the TPL '${TPL_NAME}' is on your system then you can set:\n"
|
|
" -D${TPL_NAME}_INCLUDE_DIRS='<dir0>;<dir1>;...'\n"
|
|
" to point to directories where these header files may be found.\n"
|
|
" Or, just set:\n"
|
|
" -DTPL_${TPL_NAME}_INCLUDE_DIRS='<dir0>;<dir1>;...'\n"
|
|
" to point to the include directories which will bypass any search for\n"
|
|
" header files and these include directories will be used without\n"
|
|
" question in the build. (But this will result in a build-time error\n"
|
|
" obviously if the necessary header files are not found in these\n"
|
|
" include directories.)")
|
|
tribits_tpl_find_include_dirs_and_libraries_handle_fail()
|
|
endif()
|
|
|
|
if (TPL_${TPL_NAME}_INCLUDE_DIRS)
|
|
message("-- Found TPL '${TPL_NAME}' include dirs '${TPL_${TPL_NAME}_INCLUDE_DIRS}'")
|
|
endif()
|
|
else()
|
|
|
|
# TPL_${TPL_NAME}_INCLUDE_DIRS is already in the cache so leave it alone!
|
|
|
|
endif()
|
|
|
|
# Print the final value to be used *always*
|
|
message("-- TPL_${TPL_NAME}_INCLUDE_DIRS='${TPL_${TPL_NAME}_INCLUDE_DIRS}'")
|
|
|
|
else()
|
|
|
|
if (${TPL_NAME}_INCLUDE_DIRS)
|
|
advanced_set(TPL_${TPL_NAME}_INCLUDE_DIRS ${${TPL_NAME}_INCLUDE_DIRS}
|
|
CACHE PATH "User provided include dirs in the absence of include files.")
|
|
else()
|
|
if ("${TPL_${TPL_NAME}_INCLUDE_DIRS}" STREQUAL "")
|
|
# Library has no header files, no user override, so just set them to
|
|
# null (unless the user has already set this).
|
|
global_null_set(TPL_${TPL_NAME}_INCLUDE_DIRS)
|
|
endif()
|
|
endif()
|
|
|
|
endif()
|
|
|
|
# Set library directories to null always. We do this because
|
|
# the package support code expects this variable and it is used
|
|
# for package dependencies. Therefore, we need it to allow
|
|
# TPLs and internal packages to be treated in the same way.
|
|
global_null_set(TPL_${TPL_NAME}_LIBRARY_DIRS)
|
|
|
|
if (TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES_VERBOSE)
|
|
print_var(TPL_${TPL_NAME}_LIBRARY_DIRS)
|
|
endif()
|
|
# 2011/05/09: rabartl: ToDo: Remove this above variable from everywhere!
|
|
|
|
#print_var(TPL_TENTATIVE_ENABLE_${TPL_NAME})
|
|
#print_var(_${TPL_NAME}_ENABLE_SUCCESS)
|
|
if (TPL_TENTATIVE_ENABLE_${TPL_NAME})
|
|
if (_${TPL_NAME}_ENABLE_SUCCESS)
|
|
if (NOT PARSE_NO_PRINT_ENABLE_SUCCESS_FAIL)
|
|
message("-- Attempt to tentatively enable TPL '${TPL_NAME}' passed!")
|
|
endif()
|
|
else()
|
|
if (NOT PARSE_NO_PRINT_ENABLE_SUCCESS_FAIL)
|
|
message("-- Attempt to tentatively enable TPL '${TPL_NAME}' failed!"
|
|
" Setting TPL_ENABLE_${TPL_NAME}=OFF")
|
|
endif()
|
|
set(TPL_ENABLE_${TPL_NAME} OFF CACHE STRING
|
|
"Forced off since tentative enable failed!" FORCE)
|
|
endif()
|
|
endif()
|
|
|
|
if (_${TPL_NAME}_ENABLE_SUCCESS)
|
|
global_set(TPL_${TPL_NAME}_NOT_FOUND FALSE)
|
|
endif()
|
|
|
|
set(buildDirExternalPkgsDir
|
|
"${${PROJECT_NAME}_BINARY_DIR}/${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}")
|
|
set(tplConfigFileBaseDir "${buildDirExternalPkgsDir}/${TPL_NAME}")
|
|
set(tplConfigFile "${tplConfigFileBaseDir}/${TPL_NAME}Config.cmake")
|
|
tribits_extpkg_write_config_file(${TPL_NAME} "${tplConfigFile}")
|
|
if (NOT ${PROJECT_NAME}_ENABLE_INSTALLATION_TESTING)
|
|
include("${tplConfigFile}")
|
|
endif()
|
|
# NOTE: The file <tplName>ConfigVersion.cmake will get created elsewhere as
|
|
# will the install targets for the files <tplName>Config and
|
|
# <tplName>ConfigVersion.cmake.
|
|
|
|
endfunction()
|
|
|
|
|
|
# @FUNCTION: tribits_tpl_tentatively_enable()
|
|
#
|
|
# Function that sets up for an optionally enabled TPL that is attempted to be
|
|
# enabled but will be disabled if all of the parts are not found.
|
|
#
|
|
# Usage::
|
|
#
|
|
# tribits_tpl_tentatively_enable(<tplName>)
|
|
#
|
|
# This function can be called from any CMakeLists.txt file to put a TPL in
|
|
# tentative enable mode. But typically, it is called from an Package's
|
|
# `<packageDir>/cmake/Dependencies.cmake`_ file (see `How to tentatively
|
|
# enable an external package/TPL`_).
|
|
#
|
|
# This should only be used for optional TPLs. It will not work correctly for
|
|
# required TPLs because any enabled packages that require this TPL will not be
|
|
# disabled and instead will fail to configure or fail to build.
|
|
#
|
|
# All this function does is to force set ``TPL_ENABLE_<tplName>=ON`` if it has
|
|
# not already been set, and sets ``TPL_TENTATIVE_ENABLE_<tplName>=ON`` in the
|
|
# cache.
|
|
#
|
|
# NOTE: This function will only tentatively enable a TPL if its enable has not
|
|
# be explicitly set on input, i.e. if ``-D TPL_ENABLE_<tplName>=""``. If the
|
|
# TPL has been explicitly enabled (i.e. ``-D TPL_ENABLE_<tplName>=ON``) or
|
|
# disabled (i.e. ``-D TPL_ENABLE_<tplName>=OFF``), then this function has no
|
|
# effect and the TPL will be unconditionally enabled or disabled.
|
|
#
|
|
function(tribits_tpl_tentatively_enable TPL_NAME)
|
|
|
|
if ("${TPL_ENABLE_${TPL_NAME}}" STREQUAL "")
|
|
# The TPL's enable status has not been set so tentatively enable it.
|
|
set(TPL_ENABLE_${TPL_NAME} ON CACHE STRING
|
|
"Set by tribits_tpl_tentatively_enable()" FORCE)
|
|
advanced_set(TPL_TENTATIVE_ENABLE_${TPL_NAME} ON CACHE STRING
|
|
"Set by tribits_tpl_tentatively_enable()" FORCE)
|
|
else()
|
|
# The TPL's enable status has already be hard set to be ON or OFF so we
|
|
# will leave it alone.
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
|
|
# Set find error and print error message
|
|
#
|
|
macro(tribits_tpl_find_include_dirs_and_libraries_handle_fail)
|
|
set(_${TPL_NAME}_ENABLE_SUCCESS FALSE)
|
|
global_set(TPL_${TPL_NAME}_NOT_FOUND TRUE)
|
|
message(
|
|
"-- ERROR: Failed finding all of the parts of TPL '${TPL_NAME}' (see above), Aborting!\n" )
|
|
if ("${ERROR_MSG_MODE}" STREQUAL "SEND_ERROR")
|
|
#message("ERROR_MSG_MODE=SEND_ERROR, Aborting")
|
|
return()
|
|
endif()
|
|
endmacro()
|
|
|