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 branches found
No related tags found
No related merge requests found
......@@ -32,6 +32,7 @@ set(ARB_VALIDATION_DATA_DIR "${PROJECT_SOURCE_DIR}/validation/data" CACHE PATH
#----------------------------------------------------------
# Configure-time features for Arbor:
#----------------------------------------------------------
option(ARB_WITH_GPU "build with GPU 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)
# Global CMake configuration
#----------------------------------------------------------
# Use GNU standard installation path conventions.
include(GNUInstallDirs)
# Include own CMake modules in search path, load common modules.
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
......@@ -98,16 +96,22 @@ set(CMAKE_CXX_STANDARD 14)
# 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.
# for the arbor library.
add_library(arbor-private-deps INTERFACE)
install(TARGETS arbor-private-deps EXPORT arbor-targets)
# Interface library `arbor-public-deps` collects requirements for the
# users of the arbor library (e.g. mpi) that will become part
# of arbor's PUBLIC interface.
add_library(arbor-public-deps INTERFACE)
install(TARGETS arbor-public-deps EXPORT arbor-targets)
# External libraries in `ext` sub-directory: json and tclap.
# Creates interface libraries `ext-json` and `ext-tclap`.
......@@ -119,6 +123,11 @@ add_subdirectory(ext)
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
#---------------------------------------------------------------------------
if(ARB_ARCH)
......@@ -143,6 +152,8 @@ find_package(Threads REQUIRED)
find_threads_cuda_fix()
target_link_libraries(arbor-private-deps INTERFACE Threads::Threads)
list(APPEND arbor_export_dependencies "Threads\;REQUIRED")
# MPI support
#-------------------
......@@ -160,6 +171,9 @@ if(ARB_WITH_MPI)
target_link_libraries(mpi-wrap INTERFACE MPI::MPI_CXX)
target_compile_definitions(mpi-wrap INTERFACE MPICH_SKIP_MPICXX=1 OMPI_SKIP_MPICXX=1)
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()
# CUDA support
......@@ -187,6 +201,8 @@ find_package(Unwind)
if(Unwind_FOUND)
target_link_libraries(arbor-private-deps INTERFACE Unwind::unwind)
target_compile_definitions(arbor-private-deps ARB_WITH_UNWIND)
list(APPEND arbor_export_dependencies "Unwind\;REQUIRED")
endif()
# Build and use modcc unless explicit path given
......@@ -212,9 +228,47 @@ if(ARB_WITH_PROFILING)
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:
add_subdirectory(include)
......@@ -242,3 +296,33 @@ if(ARB_BUILD_VALIDATION_DATA)
add_subdirectory(validation) # validation-data
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()
# 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.
# 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)
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
# variable, build_all_mods target. Note: CMake source file properties are
......@@ -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 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)
install(DIRECTORY arbor ${CMAKE_CURRENT_BINARY_DIR}/arbor
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
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