 e4f94fabd2
			
		
	
	e4f94fabd2
	
	
	
		
			
			* 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
		
	
		
			
				
	
	
		
			361 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			CMake
		
	
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			CMake
		
	
	
	
	
	
| # ==============================================================================
 | |
| # 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 ()
 |