Enable build configuration with CMake (#18)

* add: CMake configuration files

* doc: Variables affecting CMake configuration installation

* fix: Rename CMake module and project -> subproject macro

The problem is that macro/function definitions in CMake have global scope. Therefore, use a custom macro name rather than replacing the standard CMake command.

* enh: Set LibLBFGS_LIBRARIES variable in LibLBFGSConfig.cmake

For (older) libLBFGS installations that do not contain the CMake package configuration file, a FindLibLBFGS.cmake module will be needed which then sets LibLBFGS_LIBRARIES to the path of the actual library file instead of an imported CMake build target.

* doc: Update CMakeLists.txt comment

* fix: Do not inherit CMake options from parent project

The parent project must explicitly set ${PROJECT_NAME}_${varname} before including the subproject to the value of the same named parent option ${varname} if super- and sub-project should both use the same value.

* fix: Export of targets as part of parent project

* fix: Do not import targets when liblbfgs TARGET exists

* enh: Prefix Subproject module functions, use unique target names and non-imported target ALIAS

* enh: Remove check if PROJECT_NAME is defined

* fix: Update documentation of CMakeLists.txt

* enh: Document LBFGS_INSTALL_HEADERS
This commit is contained in:
Andreas Schuh 2019-06-04 13:04:00 +01:00 committed by Sangwhan "fish" Moon
parent 6aa4a77c99
commit e4f94fabd2
3 changed files with 616 additions and 0 deletions

241
CMakeLists.txt Normal file
View File

@ -0,0 +1,241 @@
#.rst
# CMake configuration of libLBFGS project
# ---------------------------------------
#
# This CMakeLists.txt defines some libLBFGS specific configuration variables
# using a custom "subproject_define" command defined in the Subproject.cmake module.
# The default values of these variables can be overridden either on the CMake
# command-line using the -D option of the cmake command or in a super-project
# which includes the libLBFGS source tree by setting the LBFGS_<varname>
# CMake variables before adding the libLBFGS source directory via CMake's
# add_subdirectory command. Only when the non-cached variable LBFGS_IS_SUBPROJECT
# has a value equivalent to FALSE, these configuration variables are added to
# the CMake cache so they can be edited in the CMake GUI. By default,
# LBFGS_IS_SUBPROJECT is set to TRUE when the CMAKE_SOURCE_DIR is not identical
# to the directory of this CMakeLists.txt file, i.e., the top-level directory of
# the libLBFGS project source tree.
#
# Example CMakeLists.txt of user project which requires separate libLBFGS
# installation (possibly requires FindLBFGS.cmake module for distribution
# packages of libLBFGS that do not include a LBFGSConfig.cmake file)::
#
# cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
#
# project(Foo)
#
# find_package(LBFGS REQUIRED)
#
# add_executable(foo src/foo.cc)
# target_link_libraries(foo LBFGS::lib)
#
# Example CMakeLists.txt of super-project which contains libLBFGS source tree::
#
# cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
#
# project(Foo)
#
# set(LBFGS_USE_SSE ON)
# set(LBFGS_lib_TARGET_NAME liblbfgs)
# add_subdirectory(lbfgs)
# set_target_properties(liblbfgs PROPERTIES OUTPUT_NAME foolbfgs)
#
# add_executable(foo src/foo.cc)
# target_link_libraries(foo liblbfgs)
# # or use the usual namespaced ALIAS target:
# #target_link_libraries(foo LBFGS::lib)
#
# Variables to configure the source files::
#
# LBFGS_USE_DOUBLE - Enable double precision floating point arithmetics. (default: ON)
# LBFGS_USE_SSE - Enable SSE/SSE2 optimiations. (default: OFF)
# LBFGS_USE_IEEE754 - Enable optimization routines for IEEE754 floating point values. (default: ON)
#
# Variables to configure the build::
#
# LBFGS_BUILD_SHARED_LIBS - Enable build of shared libraries. (default: OFF)
# LBFGS_BUILD_EXAMPLES - Enable build of example programs. (default: OFF)
# LBFGS_<target>_TARGET_NAME - Custom target name for target <target>, i.e., "lib" or "sample".
# By default, the target name is prefixed by "lbfgs_" if this project
# is configured as a subproject of another project.
# LBFGS_NO_ALIASES - Do not add ALIAS targets LBFGS::lib and LBFGS::sample. (default: OFF)
#
# Variables to configure the installation::
#
# LBFGS_INSTALL_STATIC_LIBS - Whether to install static library files.
# Shared libraries are always installed.
# When a library is installed, its public header
# files are installed as well. The default is
# to not install static libraries when this
# project is a subproject of another project.
# LBFGS_INSTALL_HEADERS - Can be used to omit installation of public header files.
# LBFGS_INSTALL_CONFIG - Whether to install CMake configuration files.
# By default, the CMake configuration files are
# installed when the library itself is installed.
# LBFGS_INSTALL_RUNTIME_DIR - Installation directory for runtime files. (default: bin)
# LBFGS_INSTALL_INCLUDE_DIR - Installation directory for public header files. (default: include)
# LBFGS_INSTALL_LIBRARY_DIR - Installation directory for library files. (default: lib)
# LBFGS_INSTALL_CONFIG_DIR - Installation directory for CMake configuration. (default: lib/cmake/liblbfgs)
# ==============================================================================
# libLBFGS: C library of limited-memory BFGS (L-BFGS)
#
# Copyright (c) 1990, Jorge Nocedal
# Copyright (c) 2007-2010, Naoaki Okazaki
#
# libLBFGS is distributed under the term of the MIT license.
# Please refer to COPYING file in the distribution.
# ==============================================================================
# ----------------------------------------------------------------------------
# CMake version and policies
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif ()
# ----------------------------------------------------------------------------
# includes
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Subproject.cmake")
# ----------------------------------------------------------------------------
# package info
subproject(LBFGS VERSION 1.10.0 LANGUAGES C)
set(PACKAGE_NAME "libLBFGS")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PROJECT_VERSION}")
set(PACKAGE_TARNAME "liblbfgs-${PROJECT_VERSION}")
set(PACKAGE_BUGREPORT "https://github.com/chokkan/liblbfgs/issues")
# ----------------------------------------------------------------------------
# options
subproject_define(BOOL BUILD_SHARED_LIBS "Enable build of shared libraries" OFF)
subproject_define(BOOL BUILD_EXAMPLES "Enable build of sample programs" OFF)
subproject_define(BOOL USE_DOUBLE "Use double precision floating point arithmetics" ON)
subproject_define(BOOL USE_SSE "Use SSE/SSE2 instructions for optimization" OFF)
subproject_define(BOOL USE_IEEE754 "Activate optimization routines for IEEE754 floating point values" ON)
subproject_set_property(USE_IEEE754 ADVANCED TRUE)
# ----------------------------------------------------------------------------
# checks for SSE/SSE2 instructions header files
if (USE_SSE)
include(CheckIncludeFile)
if (USE_DOUBLE)
check_include_file(emmintrin.h HAVE_EMMINTRIN_H)
if (NOT HAVE_EMMINTRIN_H)
message(WARNING "SSE2 instructions header file emmintrin.h not found. Disabled SSE optimizations.")
subproject_set_property(USE_SSE VALUE OFF)
endif ()
else ()
check_include_file(xmmintrin.h HAVE_XMMINTRIN_H)
if (NOT HAVE_XMMINTRIN_H)
message(WARNING "SSE instructions header file xmmintrin.h not found. Disabled SSE optimizations.")
subproject_set_property(USE_SSE VALUE OFF)
endif ()
endif ()
endif ()
# ----------------------------------------------------------------------------
# library
set(HEADERS
"include/lbfgs.h"
)
set(SOURCES
"lib/lbfgs.c"
"lib/arithmetic_ansi.h"
"lib/arithmetic_sse_float.h"
"lib/arithmetic_sse_double.h"
)
subproject_add_library(_lib "lib" ${HEADERS} ${SOURCES})
set_target_properties(${_lib} PROPERTIES
OUTPUT_NAME lbfgs
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}
DEBUG_POSTFIX d
POSITION_INDEPENDENT_CODE TRUE
)
target_include_directories(${_lib}
PUBLIC "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
PRIVATE "${PROJECT_SOURCE_DIR}/lib"
)
if (NOT USE_DOUBLE)
target_compile_definitions(${_lib} INTERFACE LBFGS_FLOAT=32)
endif ()
if (NOT USE_IEEE754)
target_compile_definitions(${_lib} INTERFACE LBFGS_IEEE_FLOAT=0)
endif ()
if (USE_SSE)
if (USE_DOUBLE)
target_compile_definitions(${_lib} PRIVATE HAVE_EMMINTRIN_H=${HAVE_EMMINTRIN_H})
if (MSVC)
target_compile_definitions(${_lib} PRIVATE __SSE2__)
endif ()
else ()
target_compile_definitions(${_lib} PRIVATE HAVE_XMMINTRIN_H=${HAVE_XMMINTRIN_H})
if (MSVC)
target_compile_definitions(${_lib} PRIVATE __SSE__)
endif ()
endif ()
endif ()
if (CMAKE_COMPILER_IS_GNUC)
target_compile_options(${_lib} PRIVATE "$<$<CONFIG:Release>:-ffast-math>")
if (USE_SSE)
if (USE_DOUBLE)
target_compile_options(${_lib} PRIVATE "-msse2")
else ()
target_compile_options(${_lib} PRIVATE "-msse")
endif ()
endif ()
endif ()
subproject_install_library(${_lib}
RUNTIME_DESTINATION "bin"
LIBRARY_DESTINATION "lib"
INCLUDE_DESTINATION "include"
PUBLIC_HEADER_FILES "${HEADERS}"
)
# ----------------------------------------------------------------------------
# examples
if (BUILD_EXAMPLES)
subproject_add_executable(_sample "sample" sample/sample.c)
target_link_libraries(${_sample} ${_lib})
endif ()
# ----------------------------------------------------------------------------
# configuration
include(CMakePackageConfigHelpers)
subproject_get_install_config_dir(PROJECT_INSTALL_CONFIG_DIR)
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${PROJECT_INSTALL_CONFIG_DIR}"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
subproject_install_config_files(
FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION
"${PROJECT_INSTALL_CONFIG_DIR}"
)
subproject_export(TARGETS ${_lib})
subproject_install_exports(DESTINATION "${PROJECT_INSTALL_CONFIG_DIR}")

15
cmake/Config.cmake.in Normal file
View File

@ -0,0 +1,15 @@
## @PROJECT_NAME@ CMake configuration file
# library version information
set(@PROJECT_NAME@_VERSION_STRING "@PROJECT_VERSION@")
set(@PROJECT_NAME@_VERSION_MAJOR @PROJECT_VERSION_MAJOR@)
set(@PROJECT_NAME@_VERSION_MINOR @PROJECT_VERSION_MINOR@)
set(@PROJECT_NAME@_VERSION_PATCH @PROJECT_VERSION_PATCH@)
# import exported targets
if (NOT TARGET @PROJECT_NAME@::lib)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
endif ()
# project libraries
set(@PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::lib)

360
cmake/Subproject.cmake Normal file
View File

@ -0,0 +1,360 @@
# ==============================================================================
# Utility CMake functions for standalone or subproject build configuration.
#
# This CMake source file is released into the public domain.
#
# Author: Andreas Schuh (andreas.schuh.84@gmail.com)
# ==============================================================================
include(CMakeParseArguments)
# ----------------------------------------------------------------------------
## Start (sub-)project
#
# This macro is for CMake versions 2.8.12 which did not have the VERSION
# argument yet. It additionally sets the PROJECT_SOVERSION to either the
# project major version number or ${PROJECT_NAME}_SOVERSION if set.
# When ${PROJECT_NAME}_IS_SUBPROJECT is not defined, PROJECT_IS_SUBPROJECT
# is set to TRUE when the source directory of this project is not the
# top-level source directory, and FALSE otherwise.
#
# Besides the PROJECT_NAME variable, this macro also sets PROJECT_NAME_LOWER
# and PROJECT_NAME_UPPER to the respective all lower- or uppercase strings.
macro (subproject name)
cmake_parse_arguments("" "" "VERSION;SOVERSION" "LANGUAGES" ${ARGN})
if (_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unrecognized arguments: ${_UNPARSED_ARGUMENTS}")
endif ()
if (NOT _VERSION)
set(_VERSION 0.0.0) # invalid version number
endif ()
unset(PROJECT_VERSION)
unset(PROJECT_VERSION_MAJOR)
unset(PROJECT_VERSION_MINOR)
unset(PROJECT_VERSION_PATCH)
unset(${name}_VERSION)
unset(${name}_VERSION_MAJOR)
unset(${name}_VERSION_MINOR)
unset(${name}_VERSION_PATCH)
project(${name} ${_LANGUAGES})
set(PROJECT_VERSION "${_VERSION}")
_subproject_split_version_numbers(${PROJECT_VERSION}
PROJECT_VERSION_MAJOR
PROJECT_VERSION_MINOR
PROJECT_VERSION_PATCH
)
set(${name}_VERSION ${PROJECT_VERSION})
set(${name}_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(${name}_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(${name}_VERSION_PATCH ${PROJECT_VERSION_PATCH})
if (NOT _SOVERSION)
set(_SOVERSION ${PROJECT_VERSION_MAJOR})
endif ()
_subproject_set_abi_version(PROJECT_SOVERSION ${_SOVERSION})
set(${name}_SOVERSION ${PROJECT_SOVERSION})
_subproject_check_if_subproject()
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
unset(_VERSION)
unset(_SOVERSION)
unset(_LANGUAGES)
unset(_UNPARSED_ARGUMENTS)
if (${PROJECT_NAME}_EXPORT_NAME)
set(PROJECT_EXPORT_NAME ${${PROJECT_NAME}_EXPORT_NAME})
else ()
set(PROJECT_EXPORT_NAME ${PROJECT_NAME})
endif ()
set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAVE_EXPORT FALSE)
endmacro ()
# ----------------------------------------------------------------------------
## Add configuration variable
#
# The default value of the (cached) configuration value can be overridden
# either on the CMake command-line or the super-project by setting the
# ${PROJECT_NAME}_${varname} variable. When this project is a subproject
# of another project, i.e., PROJECT_IS_SUBPROJECT is TRUE, the variable
# is not added to the CMake cache and set to the value of
# ${PROJECT_NAME}_${varname} regardless if the parent project defines
# a (cached) variable of the same name. Otherwise, when this project is
# a standalone project, the variable is cached.
macro (subproject_define type varname docstring default)
if (ARGC GREATER 5)
message (FATAL_ERROR "Too many macro arguments")
endif ()
if (NOT DEFINED ${PROJECT_NAME}_${varname})
if (PROJECT_IS_SUBPROJECT AND ARGC EQUAL 5)
set(${PROJECT_NAME}_${varname} "${ARGV4}")
else ()
set(${PROJECT_NAME}_${varname} "${default}")
endif ()
endif ()
if (PROJECT_IS_SUBPROJECT)
set(${varname} "${${PROJECT_NAME}_${varname}}")
else ()
set(${varname} "${${PROJECT_NAME}_${varname}}" CACHE ${type} "${docstring}")
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Set property of (cached) configuration variable
#
# This command does nothing when the previously defined variable was not added
# to the CMake cache because this project is build as subproject unless
# the property to be set is the VALUE of the configuration variable.
#
# @see subproject_define
macro (subproject_set_property varname property value)
_subproject_check_if_cached(_is_cached ${varname})
if (_is_cached)
if (property STREQUAL ADVANCED)
if (${value})
mark_as_advanced(FORCE ${varname})
else ()
mark_as_advanced(CLEAR ${varname})
endif ()
else ()
set_property(CACHE ${varname} PROPERTY "${property}" "${value}")
endif ()
elseif (property STREQUAL VALUE)
set(${varname} "${value}")
endif ()
unset(_is_cached)
endmacro ()
# ----------------------------------------------------------------------------
## Get unique target name
macro (subproject_target_name uid target)
if (${PROJECT_NAME}_${target}_TARGET_NAME)
set(${uid} ${${PROJECT_NAME}_${target}_TARGET_NAME})
elseif (PROJECT_IS_SUBPROJECT)
set(${uid} "${PROJECT_NAME_LOWER}_${target}")
else ()
set(${uid} "${target}")
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Add executable target
function (subproject_add_executable uid target)
subproject_target_name(_uid ${target})
add_executable(${_uid} ${ARGN})
if (NOT ${PROJECT_NAME}_NO_ALIASES)
add_executable(${PROJECT_NAME}::${target} ALIAS ${_uid})
endif ()
set(${uid} "${_uid}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## Add library target
function (subproject_add_library uid target)
subproject_target_name(_uid ${target})
add_library(${_uid} ${ARGN})
if (NOT ${PROJECT_NAME}_NO_ALIASES)
add_library(${PROJECT_NAME}::${target} ALIAS ${_uid})
endif ()
set(${uid} "${_uid}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
## Install files of library target
function (subproject_install_library target)
# parse arguments
if (NOT TARGET ${target})
message(FATAL_ERROR "Unknown target: ${target}")
endif ()
get_target_property(type ${target} TYPE)
if (NOT PROJECT_IS_SUBPROJECT OR NOT "^${type}$" STREQUAL "^STATIC_LIBRARY$" OR ${PROJECT_NAME}_INSTALL_STATIC_LIBS)
cmake_parse_arguments(""
""
"INCLUDE_DESTINATION;LIBRARY_DESTINATION;RUNTIME_DESTINATION"
"PUBLIC_HEADER_FILES"
${ARGN}
)
if (_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Too many or unrecognized arguments: ${_UNPARSED_ARGUMENTS}")
endif ()
# override (default) arguments
if (${PROJECT_NAME}_INSTALL_RUNTIME_DIR)
set(_RUNTIME_DESTINATION "${${PROJECT_NAME}_INSTALL_RUNTIME_DIR}")
elseif (NOT _RUNTIME_DESTINATION)
set(_RUNTIME_DESTINATION bin)
endif ()
if (${PROJECT_NAME}_INSTALL_INCLUDE_DIR)
set(_INCLUDE_DESTINATION "${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}")
elseif (NOT _INCLUDE_DESTINATION)
set(_INCLUDE_DESTINATION include)
endif ()
if (${PROJECT_NAME}_INSTALL_LIBRARY_DIR)
set(_LIBRARY_DESTINATION "${${PROJECT_NAME}_INSTALL_LIBRARY_DIR}")
elseif (NOT _LIBRARY_DESTINATION)
set(_LIBRARY_DESTINATION lib)
endif ()
# skip installation of static subproject library
if (_PUBLIC_HEADER_FILES AND (NOT DEFINED ${PROJECT_NAME}_INSTALL_HEADERS OR ${PROJECT_NAME}_INSTALL_HEADERS))
install(FILES ${_PUBLIC_HEADER_FILES} DESTINATION ${_INCLUDE_DESTINATION} COMPONENT Development)
target_include_directories(${target} INTERFACE "$<INSTALL_INTERFACE:${_INCLUDE_DESTINATION}>")
endif ()
install(TARGETS ${target} EXPORT ${PROJECT_EXPORT_NAME}
RUNTIME DESTINATION ${_RUNTIME_DESTINATION} COMPONENT RuntimeLibraries
LIBRARY DESTINATION ${_LIBRARY_DESTINATION} COMPONENT RuntimeLibraries
ARCHIVE DESTINATION ${_LIBRARY_DESTINATION} COMPONENT Development
)
set_property(GLOBAL PROPERTY ${PROJECT_NAME}_HAVE_EXPORT TRUE)
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## Whether to install package configuration files of (sub-)project
macro (subproject_get_install_config_option var)
if (PROJECT_IS_SUBPROJECT AND ${PROJECT_NAME}_INSTALL_CONFIG)
set (${var} 1)
elseif (NOT PROJECT_IS_SUBPROJECT AND (NOT DEFINED ${PROJECT_NAME}_INSTALL_CONFIG OR ${PROJECT_NAME}_INSTALL_CONFIG))
set (${var} 1)
else ()
set (${var} 0)
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Get relative path of package configuration installation directory
macro (subproject_get_install_config_dir config_dir)
if (${PROJECT_NAME}_INSTALL_CONFIG_DIR)
set(${config_dir} "${${PROJECT_NAME}_INSTALL_CONFIG_DIR}")
elseif (WIN32 AND NOT MINGW AND NOT CYGWIN)
set(${config_dir} "cmake")
else ()
set(${config_dir} "lib/cmake/${PROJECT_NAME_LOWER}")
endif ()
endmacro ()
# ----------------------------------------------------------------------------
## Install package configuration files
function (subproject_install_config_files)
subproject_get_install_config_option (_install_config)
if (_install_config)
# parse arguments
cmake_parse_arguments("" "" "DESTINATION" "FILES" ${ARGN})
if (_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unrecognized arguments: ${_UNPARSED_ARGUMENTS}")
endif ()
if (${PROJECT_NAME}_INSTALL_CONFIG_DIR OR NOT _DESTINATION)
subproject_get_install_config_dir(_DESTINATION)
endif ()
# install package configuration files if not overriden
install(FILES ${_FILES} DESTINATION ${_DESTINATION} COMPONENT Development)
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## Generate build tree targets configuration file
function (subproject_export)
cmake_parse_arguments("" "" "" "TARGETS" ${ARGN})
export(TARGETS ${_TARGETS} ${_UNPARSED_ARGUMENTS}
FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake"
NAMESPACE "${PROJECT_NAME}::"
)
endfunction ()
# ----------------------------------------------------------------------------
## Install exported targets configuration files
function (subproject_install_exports)
subproject_get_install_config_option (_install_config)
if (_install_config)
# parse arguments
cmake_parse_arguments("" "" "DESTINATION" "" ${ARGN})
if (_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unrecognized arguments: ${_UNPARSED_ARGUMENTS}")
endif ()
if (${PROJECT_NAME}_INSTALL_CONFIG_DIR OR NOT _DESTINATION)
subproject_get_install_config_dir(_DESTINATION)
endif ()
# install export sets
get_property(have_export GLOBAL PROPERTY ${PROJECT_NAME}_HAVE_EXPORT)
if (have_export)
install(EXPORT ${PROJECT_EXPORT_NAME}
FILE "${PROJECT_NAME}Targets.cmake"
NAMESPACE "${PROJECT_NAME}::"
DESTINATION "${_DESTINATION}"
COMPONENT Development
)
endif ()
endif ()
endfunction ()
# ==============================================================================
# Private auxiliary functions
# ==============================================================================
# ----------------------------------------------------------------------------
# Extract version numbers from version string
function (_subproject_split_version_numbers version major minor patch)
if (version MATCHES "([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(rc[1-9][0-9]*|[a-z]+)?")
if (CMAKE_MATCH_1)
set(_major ${CMAKE_MATCH_1})
else ()
set(_major 0)
endif ()
if (CMAKE_MATCH_2)
set(_minor ${CMAKE_MATCH_2})
string (REGEX REPLACE "^\\." "" _minor "${_minor}")
else ()
set(_minor 0)
endif ()
if (CMAKE_MATCH_3)
set(_patch ${CMAKE_MATCH_3})
string(REGEX REPLACE "^\\." "" _patch "${_patch}")
else ()
set(_patch 0)
endif ()
else ()
set(_major 0)
set(_minor 0)
set(_patch 0)
endif ()
set("${major}" "${_major}" PARENT_SCOPE)
set("${minor}" "${_minor}" PARENT_SCOPE)
set("${patch}" "${_patch}" PARENT_SCOPE)
endfunction ()
# ----------------------------------------------------------------------------
# Set ABI version number
#
# When the variable ${PROJECT_NAME}_SOVERSION is set, it overrides the ABI
# version number argument.
macro (_subproject_set_abi_version varname number)
if (${PROJECT_NAME}_SOVERSION)
set(${varname} "${${PROJECT_NAME}_SOVERSION}")
else ()
set(${varname} "${number}")
endif ()
endmacro ()
# ----------------------------------------------------------------------------
# Determine if project is build as subproject
#
# When included as subproject (e.g., as Git submodule/subtree) in the source
# tree of a project that uses it, no variables should be added to the CMake cache;
# users may set the (non-cached) variable ${PROJECT_NAME}_IS_SUBPROJECT before
# the add_subdirectory command that adds this subdirectory to the build.
#
# @returns Sets PROJECT_IS_SUBPROJECT to either TRUE or FALSE.
macro (_subproject_check_if_subproject)
if (DEFINED ${PROJECT_NAME}_IS_SUBPROJECT)
set(PROJECT_IS_SUBPROJECT ${PROJECT_NAME}_IS_SUBPROJECT)
elseif ("^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
set(PROJECT_IS_SUBPROJECT FALSE)
else ()
set(PROJECT_IS_SUBPROJECT TRUE)
endif ()
endmacro ()
# ----------------------------------------------------------------------------
# Determine if cache entry exists
macro (_subproject_check_if_cached retvar varname)
if (DEFINED ${varname})
get_property(${retvar} CACHE ${varname} PROPERTY TYPE SET)
else ()
set(${retvar} FALSE)
endif ()
endmacro ()