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:

committed by
Sangwhan "fish" Moon

parent
6aa4a77c99
commit
e4f94fabd2
15
cmake/Config.cmake.in
Normal file
15
cmake/Config.cmake.in
Normal 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
360
cmake/Subproject.cmake
Normal 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 ()
|
Reference in New Issue
Block a user