diff --git a/CMakeLists.txt b/CMakeLists.txt index 72fa64c1..dee45877 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,10 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") endif() endif() +### Get software version +find_package(Git) +include(GetProjectVersionFromGit) +get_project_version_from_git("${PROJECT_NAME}" "${CMAKE_CURRENT_SOURCE_DIR}" "${GIT_EXECUTABLE}") ### Handle windows-specific fixes if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") @@ -41,21 +45,22 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions (-D_USE_MATH_DEFINES) # match unix behavior of constants in cmath endif() +# Set up our directory structure for output libraries and binaries +include(GNUInstallDirs) + ### Do anything needed for dependencies and bring their stuff in to scope add_subdirectory(deps) -# copy variables set by deps upward -SET(GC_HAVE_SUITESPARSE ${GC_HAVE_SUITESPARSE} PARENT_SCOPE) - ### Recurse to the source code add_subdirectory(src) # install install( TARGETS geometry-central - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib) + EXPORT GeometryCentral + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install( DIRECTORY ${CMAKE_SOURCE_DIR}/include/ @@ -63,3 +68,31 @@ install( FILES_MATCHING PATTERN "*.h" PATTERN "*.ipp") + +install(EXPORT GeometryCentral + FILE + geometrycentral.cmake + NAMESPACE + geometrycentral:: + DESTINATION + ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) + +include(CMakePackageConfigHelpers) +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/geometrycentral-config-install.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/geometrycentral-config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/geometrycentral-config-version.cmake" + VERSION ${${PROJECT_NAME}_VERSION} + COMPATIBILITY SameMajorVersion +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/geometrycentral-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/geometrycentral-config-version.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) diff --git a/cmake/GetProjectVersionFromGit.cmake b/cmake/GetProjectVersionFromGit.cmake new file mode 100644 index 00000000..9db9a51a --- /dev/null +++ b/cmake/GetProjectVersionFromGit.cmake @@ -0,0 +1,41 @@ +# This function attempts to determine the project version from git tags. +# It sets variables with a given prefix to reflect the version information. +# - version_prefix: The prefix for version-related variables. +# - project_source_dir: The directory containing the project's source code. +# - git_exe: The path to the git executable. +# +# On success, it sets variables indicating the version (major, minor, patch, etc.). +# On failure, a status message is printed. + +function(get_project_version_from_git version_prefix project_source_dir git_exe) + if(EXISTS "${git_exe}" AND EXISTS "${project_source_dir}/.git") + execute_process( + COMMAND "${git_exe}" describe --tags --always + WORKING_DIRECTORY "${project_source_dir}" + RESULT_VARIABLE git_result + OUTPUT_VARIABLE version_output + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(git_result EQUAL 0) + string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" version_parts "${version_output}") + if(version_parts) + # Extract version numbers + set(version_major "${CMAKE_MATCH_1}") + set(version_minor "${CMAKE_MATCH_2}") + set(version_patch "${CMAKE_MATCH_3}") + set(full_version "${version_major}.${version_minor}.${version_patch}") + + # Set variables in the parent scope + set("${version_prefix}_VERSION" "${full_version}" PARENT_SCOPE) + set("${version_prefix}_MAJOR" "${version_major}" PARENT_SCOPE) + set("${version_prefix}_MINOR" "${version_minor}" PARENT_SCOPE) + set("${version_prefix}_PATCH" "${version_patch}" PARENT_SCOPE) + endif() + else() + message(STATUS "Unable to determine project version from git tags.") + endif() + else() + message(STATUS "Git not available or .git directory not found.") + endif() +endfunction() diff --git a/cmake/geometrycentral-config-install.cmake.in b/cmake/geometrycentral-config-install.cmake.in new file mode 100644 index 00000000..b37ccdab --- /dev/null +++ b/cmake/geometrycentral-config-install.cmake.in @@ -0,0 +1,22 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +find_dependency(Eigen3 3.3 CONFIG) + +set(_GeometryCentral_WITH_SUITESPARSE @GC_HAVE_SUITESPARSE@) +if(_GeometryCentral_WITH_SUITESPARSE) + find_dependency(SuiteSparse CONFIG) + if(NOT TARGET SuiteSparse::cholmod) + message(FATAL_ERROR "SuiteSparse::cholmod target not found.") + endif() + if(NOT TARGET SuiteSparse::spqr) + message(FATAL_ERROR "SuiteSparse::spqr target not found.") + endif() + if(NOT TARGET SuiteSparse::umfpack) + message(FATAL_ERROR "SuiteSparse::umfpack target not found.") + endif() +endif() + +# Include the exported targets file +include("${CMAKE_CURRENT_LIST_DIR}/geometrycentral.cmake") diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 10abf8e5..a1ceec25 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -86,8 +86,15 @@ else() add_library (Eigen3::Eigen ALIAS eigen) target_include_directories(eigen INTERFACE $ - $ + $ ) + install(TARGETS eigen + EXPORT GeometryCentral + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) endif() list(APPEND GC_DEP_LIBS Eigen3::Eigen) @@ -117,26 +124,21 @@ else (SUITESPARSE) message("-- Building without SuiteSparse.") endif (SUITESPARSE) -# HACK BY NICK -# The SuiteSparse logic above doesn't look for UMFpack, but we need it. -# This code attempts to find if by assuming that it will be in the same place -# as cholmod -if(SUITESPARSE AND SUITESPARSE_FOUND) - string(REGEX REPLACE "cholmod" "umfpack" UMFPACK_LIBRARY ${CHOLMOD_LIBRARY}) - message("-- Guesstimated umfpack location as: ${UMFPACK_LIBRARY}") - if(EXISTS ${UMFPACK_LIBRARY}) - list(APPEND SUITESPARSE_LIBRARIES ${UMFPACK_LIBRARY}) - else() - message(WARNING "UMFPack guess failed, so we don't actually have SUITESPARSE support.") - set(SUITESPARSE_FOUND FALSE) - endif() -endif() - if(SUITESPARSE AND SUITESPARSE_FOUND) SET(GC_HAVE_SUITESPARSE TRUE) SET(GC_HAVE_SUITESPARSE TRUE PARENT_SCOPE) - set(SUITESPARSE_INCLUDE_DIRS "${SUITESPARSE_INCLUDE_DIRS}" PARENT_SCOPE) - set(SUITESPARSE_LIBRARIES "${SUITESPARSE_LIBRARIES}" PARENT_SCOPE) + if(NOT TARGET SuiteSparse::cholmod) + message(FATAL_ERROR "SuiteSparse::cholmod target not found.") + endif() + set_target_properties(SuiteSparse::cholmod PROPERTIES IMPORTED_GLOBAL TRUE) + if(NOT TARGET SuiteSparse::spqr) + message(FATAL_ERROR "SuiteSparse::spqr target not found.") + endif() + set_target_properties(SuiteSparse::spqr PROPERTIES IMPORTED_GLOBAL TRUE) + if(NOT TARGET SuiteSparse::umfpack) + message(FATAL_ERROR "SuiteSparse::umfpack target not found.") + endif() + set_target_properties(SuiteSparse::umfpack PROPERTIES IMPORTED_GLOBAL TRUE) else() SET(GC_HAVE_SUITESPARSE FALSE) SET(GC_HAVE_SUITESPARSE FALSE PARENT_SCOPE) @@ -147,6 +149,13 @@ endif() if (NOT TARGET nanort) add_library(nanort INTERFACE) target_include_directories(nanort INTERFACE $) + install(TARGETS nanort + EXPORT GeometryCentral + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) endif() if (NOT TARGET nanoflann) @@ -159,11 +168,25 @@ if (NOT TARGET nanoflann) ${CMAKE_CURRENT_SOURCE_DIR}/nanoflann/include/nanoflann.hpp ${CMAKE_CURRENT_BINARY_DIR}/include/nanoflann/nanoflann.hpp SYMBOLIC) target_include_directories(nanoflann INTERFACE $) + install(TARGETS nanoflann + EXPORT GeometryCentral + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) endif() if (NOT TARGET happly) add_library(happly INTERFACE) target_include_directories(happly INTERFACE $) + install(TARGETS happly + EXPORT GeometryCentral + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) endif() # Find other simpler dependencies diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dc623664..80f2360c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -171,7 +171,10 @@ SET(HEADERS add_library(geometry-central ${SRCS} ${HEADERS}) # Includes from this project -target_include_directories(geometry-central PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include") +target_include_directories(geometry-central PUBLIC + $ + $ +) # Add all includes and link libraries from dependencies, which were populated in deps/CMakeLists.txt target_link_libraries(geometry-central PUBLIC ${GC_DEP_LIBS}) @@ -187,8 +190,11 @@ target_compile_definitions(geometry-central PUBLIC NOMINMAX _USE_MATH_DEFINES) # Define CMAKE flag used in these sources (but should be kept OUT of headers) if(GC_HAVE_SUITESPARSE) target_compile_definitions(geometry-central PUBLIC GC_HAVE_SUITESPARSE) - target_include_directories(geometry-central PRIVATE ${SUITESPARSE_INCLUDE_DIRS}) - target_link_libraries(geometry-central PRIVATE ${SUITESPARSE_LIBRARIES}) + target_link_libraries(geometry-central PRIVATE + SuiteSparse::cholmod + SuiteSparse::spqr + SuiteSparse::umfpack + ) endif() # Export symbols if DLL is requested