Skip to content
Snippets Groups Projects
Commit 7ade5c26 authored by Sam Yates's avatar Sam Yates Committed by Benjamin Cumming
Browse files

Add installable CMake config for arbor (#616)

Fixes #612.

* Fix issues with permissions on directories created at install time (at least for CMake 3.11+).
* Add CMake export guff to various targets and install an `arbor-config.cmake` for consumption by other CMake-based projects.
parent 488ece0c
No related merge requests found
...@@ -32,6 +32,7 @@ set(ARB_VALIDATION_DATA_DIR "${PROJECT_SOURCE_DIR}/validation/data" CACHE PATH ...@@ -32,6 +32,7 @@ set(ARB_VALIDATION_DATA_DIR "${PROJECT_SOURCE_DIR}/validation/data" CACHE PATH
#---------------------------------------------------------- #----------------------------------------------------------
# Configure-time features for Arbor: # Configure-time features for Arbor:
#---------------------------------------------------------- #----------------------------------------------------------
option(ARB_WITH_GPU "build with GPU support" OFF) option(ARB_WITH_GPU "build with GPU support" OFF)
option(ARB_WITH_MPI "build with MPI support" OFF) option(ARB_WITH_MPI "build with MPI support" OFF)
...@@ -44,9 +45,6 @@ option(ARB_WITH_ASSERTIONS "enable arb_assert() assertions in code" OFF) ...@@ -44,9 +45,6 @@ option(ARB_WITH_ASSERTIONS "enable arb_assert() assertions in code" OFF)
# Global CMake configuration # Global CMake configuration
#---------------------------------------------------------- #----------------------------------------------------------
# Use GNU standard installation path conventions.
include(GNUInstallDirs)
# Include own CMake modules in search path, load common modules. # Include own CMake modules in search path, load common modules.
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
...@@ -98,16 +96,22 @@ set(CMAKE_CXX_STANDARD 14) ...@@ -98,16 +96,22 @@ set(CMAKE_CXX_STANDARD 14)
# Set up flags and dependencies: # Set up flags and dependencies:
#---------------------------------------------------------- #----------------------------------------------------------
# Note: any target dependency of arbor needs to be explicitly added
# to the 'export set', even the private ones, and this must be done
# in the same CMakeLists.txt in which the target is defined.
# Interface library `arbor-private-deps` collects dependencies, options etc. # Interface library `arbor-private-deps` collects dependencies, options etc.
# for the arbor library. # for the arbor library.
add_library(arbor-private-deps INTERFACE) add_library(arbor-private-deps INTERFACE)
install(TARGETS arbor-private-deps EXPORT arbor-targets)
# Interface library `arbor-public-deps` collects requirements for the # Interface library `arbor-public-deps` collects requirements for the
# users of the arbor library (e.g. mpi) that will become part # users of the arbor library (e.g. mpi) that will become part
# of arbor's PUBLIC interface. # of arbor's PUBLIC interface.
add_library(arbor-public-deps INTERFACE) add_library(arbor-public-deps INTERFACE)
install(TARGETS arbor-public-deps EXPORT arbor-targets)
# External libraries in `ext` sub-directory: json and tclap. # External libraries in `ext` sub-directory: json and tclap.
# Creates interface libraries `ext-json` and `ext-tclap`. # Creates interface libraries `ext-json` and `ext-tclap`.
...@@ -119,6 +123,11 @@ add_subdirectory(ext) ...@@ -119,6 +123,11 @@ add_subdirectory(ext)
add_subdirectory(aux) add_subdirectory(aux)
# Keep track of packages we need to add to the generated CMake config
# file for arbor.
set(arbor_export_dependencies)
# Target microarchitecture for building arbor libraries, tests and examples # Target microarchitecture for building arbor libraries, tests and examples
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
if(ARB_ARCH) if(ARB_ARCH)
...@@ -143,6 +152,8 @@ find_package(Threads REQUIRED) ...@@ -143,6 +152,8 @@ find_package(Threads REQUIRED)
find_threads_cuda_fix() find_threads_cuda_fix()
target_link_libraries(arbor-private-deps INTERFACE Threads::Threads) target_link_libraries(arbor-private-deps INTERFACE Threads::Threads)
list(APPEND arbor_export_dependencies "Threads\;REQUIRED")
# MPI support # MPI support
#------------------- #-------------------
...@@ -160,6 +171,9 @@ if(ARB_WITH_MPI) ...@@ -160,6 +171,9 @@ if(ARB_WITH_MPI)
target_link_libraries(mpi-wrap INTERFACE MPI::MPI_CXX) target_link_libraries(mpi-wrap INTERFACE MPI::MPI_CXX)
target_compile_definitions(mpi-wrap INTERFACE MPICH_SKIP_MPICXX=1 OMPI_SKIP_MPICXX=1) target_compile_definitions(mpi-wrap INTERFACE MPICH_SKIP_MPICXX=1 OMPI_SKIP_MPICXX=1)
target_link_libraries(arbor-public-deps INTERFACE mpi-wrap) target_link_libraries(arbor-public-deps INTERFACE mpi-wrap)
install(TARGETS mpi-wrap EXPORT arbor-targets)
list(APPEND arbor_export_dependencies "MPI\;REQUIRED\;CXX")
endif() endif()
# CUDA support # CUDA support
...@@ -187,6 +201,8 @@ find_package(Unwind) ...@@ -187,6 +201,8 @@ find_package(Unwind)
if(Unwind_FOUND) if(Unwind_FOUND)
target_link_libraries(arbor-private-deps INTERFACE Unwind::unwind) target_link_libraries(arbor-private-deps INTERFACE Unwind::unwind)
target_compile_definitions(arbor-private-deps ARB_WITH_UNWIND) target_compile_definitions(arbor-private-deps ARB_WITH_UNWIND)
list(APPEND arbor_export_dependencies "Unwind\;REQUIRED")
endif() endif()
# Build and use modcc unless explicit path given # Build and use modcc unless explicit path given
...@@ -212,9 +228,47 @@ if(ARB_WITH_PROFILING) ...@@ -212,9 +228,47 @@ if(ARB_WITH_PROFILING)
endif() endif()
#---------------------------------------------------------- #----------------------------------------------------------
# Configure targets in sub-directories. # Set up install paths, permissions.
#---------------------------------------------------------- #----------------------------------------------------------
# Set up install paths according to GNU conventions.
#
# GNUInstallDirs picks (e.g.) `lib64` for the library install path on some
# systems where this is definitely not correct (e.g. Arch Linux). If there
# are cases where `lib` is inappropriate, we will have to incorporate special
# case behaviour here.
if(NOT CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR lib)
endif()
include(GNUInstallDirs)
# Implicitly created directories require permissions to be set explicitly
# via this CMake variable.
#
# Note that this has no effect until CMake version 3.11.
set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
OWNER_READ
OWNER_WRITE
OWNER_EXECUTE
GROUP_READ
GROUP_EXECUTE
WORLD_READ
WORLD_EXECUTE)
# CMake versions 3.11 and 3.12 ignore this variable for directories
# implicitly created by install(DIRECTORY ...), which for us corresponds
# to our doc and include directories. Work-around by trying to install
# a non-existant file to these locations.
foreach(directory "${CMAKE_INSTALL_DOCDIR}" "${CMAKE_INSTALL_INCLUDEDIR}")
install(FILES _no_such_file_ OPTIONAL DESTINATION "${directory}")
endforeach()
#----------------------------------------------------------
# Configure targets in sub-directories.
#----------------------------------------------------------
# arbor-public-headers: # arbor-public-headers:
add_subdirectory(include) add_subdirectory(include)
...@@ -242,3 +296,33 @@ if(ARB_BUILD_VALIDATION_DATA) ...@@ -242,3 +296,33 @@ if(ARB_BUILD_VALIDATION_DATA)
add_subdirectory(validation) # validation-data add_subdirectory(validation) # validation-data
endif() endif()
#----------------------------------------------------------
# Generate CMake config/version files for install.
#----------------------------------------------------------
# Note: each dependency for the arbor library target, private or otherwise,
# needs to add itself to the arbor-exports EXPORT target in the subdirectory
# in which they are defined, or none of this will work.
set(cmake_config_dir "${CMAKE_INSTALL_LIBDIR}/cmake/arbor")
install(EXPORT arbor-targets NAMESPACE arbor:: DESTINATION "${cmake_config_dir}")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/arbor-config-version.cmake"
COMPATIBILITY SameMajorVersion)
# Template file will use contents of arbor_export_dependencies to include the
# required `find_dependency` statements.
configure_file(
cmake/arbor-config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/arbor-config.cmake"
@ONLY)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/arbor-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/arbor-config-version.cmake"
DESTINATION "${cmake_config_dir}")
...@@ -80,8 +80,15 @@ endif() ...@@ -80,8 +80,15 @@ endif()
# and arbor unit tests. Private headers are also used for the other binaries # and arbor unit tests. Private headers are also used for the other binaries
# until the process of splitting our private and public headers is complete. # until the process of splitting our private and public headers is complete.
# Because we need to add this target to the EXPORT set, and it needs to be
# installed (despite being private to arbor), we have to qualify the include
# directory with a build-time only generator expression.
add_library(arbor-private-headers INTERFACE) add_library(arbor-private-headers INTERFACE)
target_include_directories(arbor-private-headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(arbor-private-headers INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
install(TARGETS arbor-private-headers EXPORT arbor-targets)
# Mechanisms, generated from .mod files; sets arbor_mechanism_sources # Mechanisms, generated from .mod files; sets arbor_mechanism_sources
# variable, build_all_mods target. Note: CMake source file properties are # variable, build_all_mods target. Note: CMake source file properties are
...@@ -97,5 +104,5 @@ add_dependencies(arbor build_all_mods) ...@@ -97,5 +104,5 @@ add_dependencies(arbor build_all_mods)
target_link_libraries(arbor PRIVATE arbor-private-deps arbor-private-headers) target_link_libraries(arbor PRIVATE arbor-private-deps arbor-private-headers)
target_link_libraries(arbor PUBLIC arbor-public-deps arbor-public-headers) target_link_libraries(arbor PUBLIC arbor-public-deps arbor-public-headers)
install(TARGETS arbor ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS arbor EXPORT arbor-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
include(CMakeFindDependencyMacro)
foreach(dep @arbor_export_dependencies@)
find_dependency(${dep})
endforeach()
include("${CMAKE_CURRENT_LIST_DIR}/arbor-targets.cmake")
...@@ -62,3 +62,5 @@ add_dependencies(arbor-public-headers generate_version_hpp) ...@@ -62,3 +62,5 @@ add_dependencies(arbor-public-headers generate_version_hpp)
install(DIRECTORY arbor ${CMAKE_CURRENT_BINARY_DIR}/arbor install(DIRECTORY arbor ${CMAKE_CURRENT_BINARY_DIR}/arbor
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.hpp") FILES_MATCHING PATTERN "*.hpp")
install(TARGETS arbor-public-headers EXPORT arbor-targets)
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment