diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ba0e78d63332b0ff078bb83a3222c79b25fee13..948430d6bfebd61a3b6dd756e95f567d8c312b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") + diff --git a/arbor/CMakeLists.txt b/arbor/CMakeLists.txt index 74d6a3cdbeba06eb2e1bb3f6f7f00a027b5eee40..dd885eac382d8533679b9a7ec3914607a4fa1292 100644 --- a/arbor/CMakeLists.txt +++ b/arbor/CMakeLists.txt @@ -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}) diff --git a/cmake/arbor-config.cmake.in b/cmake/arbor-config.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..703e70058269727803a00d75ffa474da08799dcd --- /dev/null +++ b/cmake/arbor-config.cmake.in @@ -0,0 +1,9 @@ +include(CMakeFindDependencyMacro) + +foreach(dep @arbor_export_dependencies@) + find_dependency(${dep}) +endforeach() + +include("${CMAKE_CURRENT_LIST_DIR}/arbor-targets.cmake") + + diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 4006ec2adc485538d8667a1b5c9e24e69386ee1c..815a3b6f412a06ae8ab9583805cf5124a4aae718 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -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)