Skip to content

Commit

Permalink
Merge Enable --prefix Option for CMake Install
Browse files Browse the repository at this point in the history
This merge allows Ginkgo to use the `--prefix` option of `cmake --install`. Before, the path set by `--prefix` would just be ignored and the `CMAKE_INSTALL_PREFIX` set at configure time would be used.

In principle, this is a minor change, except for the PKG config file. Getting this to work is quite cumbersome, but it works as expected.

Changes to the pkg-config file:
- The `prefix` now uses the path specified by `--prefix` (if present)
- `libdir` and `includedir` are now relative to `prefix`
- The `-L` and `-I` paths for ginkgo also use paths relative to `prefix`

Related PR: #1534
  • Loading branch information
MarcelKoch authored Feb 14, 2024
2 parents 2918506 + 2c6836b commit 45692bd
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 126 deletions.
14 changes: 1 addition & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ unset(BASH CACHE)

# Installation
include(cmake/information_helpers.cmake)
ginkgo_interface_information()
ginkgo_pkg_information()
ginkgo_git_information()

include(cmake/get_info.cmake)
Expand All @@ -408,18 +408,6 @@ if(GINKGO_BUILD_DOC)
endif()


# add escape character '\' for space
string(REPLACE " " "\ " PKG_CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# add escape character '\' for space in regex mode
list(TRANSFORM GINKGO_INTERFACE_LINK_FLAGS REPLACE " " "\\\\ ")
list(TRANSFORM GINKGO_INTERFACE_CXX_FLAGS REPLACE " " "\\\\ ")
# convert the list to string
string(REPLACE ";" " " GINKGO_INTERFACE_CXX_FLAGS "${GINKGO_INTERFACE_CXX_FLAGS}")
string(REPLACE ";" " " GINKGO_INTERFACE_LINK_FLAGS "${GINKGO_INTERFACE_LINK_FLAGS}")
configure_file(${Ginkgo_SOURCE_DIR}/cmake/ginkgo.pc.in
${Ginkgo_BINARY_DIR}/ginkgo.pc.in @ONLY)
file(GENERATE OUTPUT ${Ginkgo_BINARY_DIR}/ginkgo_$<CONFIG>.pc
INPUT ${Ginkgo_BINARY_DIR}/ginkgo.pc.in)

# WINDOWS NVCC has " inside the string, add escape character
# to avoid config problem.
Expand Down
45 changes: 22 additions & 23 deletions cmake/GinkgoConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ set(GINKGO_CUDA_HOST_COMPILER_SHORT "") # dummy value to stay consistent
set(GINKGO_EXPORT_BINARY_DIR "@GINKGO_EXPORT_BINARY_DIR@")
if(NOT GINKGO_EXPORT_BINARY_DIR)
set_and_check(GINKGO_INSTALL_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@")
set_and_check(GINKGO_INSTALL_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@")
set_and_check(GINKGO_INSTALL_LIBRARY_DIR "@PACKAGE_CMAKE_INSTALL_FULL_LIBDIR@")
set_and_check(GINKGO_INSTALL_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
set_and_check(GINKGO_INSTALL_LIBRARY_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
set(GINKGO_INSTALL_RPATH_FOR_HIP "-Wl,-rpath,${GINKGO_INSTALL_LIBRARY_DIR}")
set(GINKGO_INSTALL_RPATH @GINKGO_INSTALL_RPATH@)
set(GINKGO_INSTALL_RPATH_USE_ORIGIN @GINKGO_INSTALL_RPATH_USE_ORIGIN@)
Expand Down Expand Up @@ -147,60 +147,59 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
# NOTE: we do not export benchmarks, examples, tests or devel tools
# so `third_party` libraries are currently unneeded.

include(CMakeFindDependencyMacro)
if(GINKGO_HAVE_PAPI_SDE)
find_package(PAPI REQUIRED COMPONENTS sde)
find_dependency(PAPI 7.0.1.0 COMPONENTS sde)
endif()

if(GINKGO_HAVE_HWLOC)
find_package(HWLOC REQUIRED)
find_dependency(HWLOC)
endif()

# Check for MPI if it is enabled
if(GINKGO_BUILD_MPI)
find_package(MPI 3.1 COMPONENTS CXX REQUIRED)
find_dependency(MPI 3.1 COMPONENTS CXX)
endif()

# HIP and OpenMP depend on Threads::Threads in some circumstances, but don't find it
if (GINKGO_BUILD_HIP OR GINKGO_BUILD_OMP)
find_package(Threads REQUIRED)
find_dependency(Threads)
endif()

# Needed because of a known issue with CUDA while linking statically.
# For details, see https://gitlab.kitware.com/cmake/cmake/issues/18614
if((NOT GINKGO_BUILD_SHARED_LIBS) AND GINKGO_BUILD_CUDA)
enable_language(CUDA)
find_package(CUDAToolkit REQUIRED)
find_package(NVTX REQUIRED)
find_dependency(CUDAToolkit)
find_dependency(NVTX)
endif()

if((NOT GINKGO_BUILD_SHARED_LIBS) AND GINKGO_BUILD_HIP)
find_package(HIP REQUIRED)
find_package(hipblas REQUIRED)
find_package(hipfft) # optional
find_package(hiprand REQUIRED)
find_package(hipsparse REQUIRED)
find_package(rocrand REQUIRED)
set(ROCTRACER_PATH "@ROCTRACER_PATH@")
if(GINKGO_HAVE_ROCTX)
find_package(ROCTX REQUIRED)
endif()
find_dependency(HIP)
find_dependency(hipblas)
find_dependency(hipfft)
find_dependency(hiprand)
find_dependency(hipsparse)
find_dependency(rocrand)
set_and_check(ROCTRACER_PATH "@ROCTRACER_PATH@")
find_dependency(ROCTX)
endif()

if((NOT GINKGO_BUILD_SHARED_LIBS) AND GINKGO_BUILD_SYCL)
find_package(MKL CONFIG REQUIRED HINTS "${GINKGO_MKL_ROOT}")
find_package(oneDPL REQUIRED HINTS "${GINKGO_DPL_ROOT}")
find_dependency(MKL CONFIG HINTS "${GINKGO_MKL_ROOT}")
find_dependency(oneDPL HINTS "${GINKGO_DPL_ROOT}")
endif()

if(GINKGO_HAVE_VTUNE)
find_package(VTune REQUIRED)
find_dependency(VTune)
endif()

if((NOT GINKGO_BUILD_SHARED_LIBS) AND GINKGO_HAVE_METIS)
find_package(METIS REQUIRED)
find_dependency(METIS)
endif()

if((NOT GINKGO_BUILD_SHARED_LIBS) AND GINKGO_HAVE_TAU)
find_package(PerfStubs REQUIRED)
find_dependency(PerfStubs)
endif()

# Check that the same compilers as for Ginkgo are used
Expand Down
35 changes: 35 additions & 0 deletions cmake/generate_pkg.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# This is run as a standalone script. Thus no cmake variables related to Ginkgo are
# available through the ${...} syntax. Instead, the file containing the actual values
# of the necessary variables is generated through `configure_file`. But this leaves
# generator expressions unresolved, so another pass through `file(GENERATE ...)` is
# necessary. That call can't be put into this file, since the script is used as part
# of `install(SCRIPT ...)` which doesn't support generator expressions in the script
# content

# add escape character '\' for space
string(REPLACE " " "\ " GINKGO_PKG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# add escape character '\' for space in regex mode
string(REPLACE ";" "\ " GINKGO_INTERFACE_LINK_FLAGS "@GINKGO_INTERFACE_LINK_FLAGS@")
string(REPLACE ";" "\ " GINKGO_INTERFACE_CXX_FLAGS "@GINKGO_INTERFACE_CXX_FLAGS@")

set(GINKGO_INSTALL_LIBDIR "@CMAKE_INSTALL_LIBDIR@")
set(GINKGO_INSTALL_INCLUDEDIR "@CMAKE_INSTALL_INCLUDEDIR@")
set(GINKGO_PROJECT_NAME "@CMAKE_PROJECT_NAME@")
set(GINKGO_DESCRIPTION "@Ginkgo_DESCRIPTION@")
set(GINKGO_VERSION "@Ginkgo_VERSION@")

set(GINKGO_INSTALL_PKGCONFIG_DIR "${GINKGO_PKG_INSTALL_PREFIX}/${GINKGO_INSTALL_LIBDIR}/pkgconfig")

set(GINKGO_SOURCE_DIR "@Ginkgo_SOURCE_DIR@")
set(GINKGO_BINARY_DIR "@Ginkgo_BINARY_DIR@")


message(STATUS "Installing: ${GINKGO_INSTALL_PKGCONFIG_DIR}/ginkgo_$<CONFIG>.pc")
configure_file(${GINKGO_SOURCE_DIR}/cmake/ginkgo.pc.in
${GINKGO_INSTALL_PKGCONFIG_DIR}/ginkgo_$<CONFIG>.pc
@ONLY)

message(STATUS "Installing: ${GINKGO_INSTALL_PKGCONFIG_DIR}/ginkgo.pc")
configure_file(${GINKGO_SOURCE_DIR}/cmake/ginkgo.pc.in
${GINKGO_INSTALL_PKGCONFIG_DIR}/ginkgo.pc
@ONLY)
12 changes: 6 additions & 6 deletions cmake/ginkgo.pc.in
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
prefix=@PKG_CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
prefix=@GINKGO_PKG_INSTALL_PREFIX@
libdir=${prefix}/@GINKGO_INSTALL_LIBDIR@
includedir=${prefix}/@GINKGO_INSTALL_INCLUDEDIR@

Name: @CMAKE_PROJECT_NAME@
Description: @Ginkgo_DESCRIPTION@
Version: @Ginkgo_VERSION@
Name: @GINKGO_PROJECT_NAME@
Description: @GINKGO_DESCRIPTION@
Version: @GINKGO_VERSION@
URL: https://ginkgo-project.github.io/

Requires:
Expand Down
146 changes: 79 additions & 67 deletions cmake/information_helpers.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# TODO: we may use file(GENERATE ... TARGET ...) to generate config file based on the target property
# when we bump the CMake minimum version to 3.15/3.19
include(GNUInstallDirs)

# This can't be replaced by `file(GENERATE ... TARGET ...)`, since the generator expressions
# might contain `COMPILE_LANG_AND_ID` which is not allowed in `file(GENERATE ...)`
function(filter_generator_expressions INPUT OUTPUT)
# See https://gitlab.kitware.com/cmake/cmake/-/blob/v3.22.2/Modules/FindMPI.cmake#L1218
# and other versions of this file for what we are removing here.
Expand All @@ -22,99 +24,109 @@ endfunction()
macro(ginkgo_interface_libraries_recursively INTERFACE_LIBS)
# always add the interface to the list to keep the order information
# Currently, it does not support the circular dependence and MSVC.
foreach(_libs ${INTERFACE_LIBS})
if (TARGET ${_libs})
if("${_libs}" MATCHES "ginkgo.*")
set(GINKGO_INTERFACE_LIB_NAME "-l${_libs}$<$<CONFIG:Debug>:${CMAKE_DEBUG_POSTFIX}>")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${GINKGO_INTERFACE_LIB_NAME}")
endif()
# Get the link flags and treat them
get_target_property(GINKGO_INTERFACE_LIBS_LINK_FLAGS "${_libs}"
INTERFACE_LINK_OPTIONS)
if (GINKGO_INTERFACE_LIBS_LINK_FLAGS)
filter_generator_expressions("${GINKGO_INTERFACE_LIBS_LINK_FLAGS}"
GINKGO_INTERFACE_LIB_NAME)
endif()
# Get the imported library
get_target_property(_libs_type "${_libs}" TYPE)
get_target_property(_libs_imported "${_libs}" IMPORTED)
if (_libs_imported AND NOT ${_libs_type} STREQUAL "INTERFACE_LIBRARY")
get_target_property(GINKGO_LIBS_IMPORTED_LIBS "${_libs}" IMPORTED_LOCATION_RELEASE)
if (NOT GINKGO_LIBS_IMPORTED_LIBS)
get_target_property(GINKGO_LIBS_IMPORTED_LIBS "${_libs}" IMPORTED_LOCATION)
foreach(_lib ${INTERFACE_LIBS})
# hash library, so we don't get any duplicates, based on
# https://gitlab.kitware.com/cmake/cmake/-/blob/v3.28.1/Modules/CMakeFindDependencyMacro.cmake#L57
string(SHA256 _gko_interface_lib_hash "${_lib}")
if(_GKO_${_gko_interface_lib_hash}_FOUND)
unset(_gko_interface_lib_hash)
else()
set("_GKO_${_gko_interface_lib_hash}_FOUND" ON)
if(TARGET ${_lib})
if("${_lib}" MATCHES "ginkgo.*")
set(GINKGO_INTERFACE_LIB_NAME "-l${_lib}$<$<CONFIG:Debug>:${CMAKE_DEBUG_POSTFIX}>")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${GINKGO_INTERFACE_LIB_NAME}")
endif()
if (GINKGO_LIBS_IMPORTED_LIBS)
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${GINKGO_LIBS_IMPORTED_LIBS}")
# Get the link flags and treat them
get_target_property(GINKGO_INTERFACE_LIBS_LINK_FLAGS "${_lib}" INTERFACE_LINK_OPTIONS)
if (GINKGO_INTERFACE_LIBS_LINK_FLAGS)
filter_generator_expressions("${GINKGO_INTERFACE_LIBS_LINK_FLAGS}"
GINKGO_INTERFACE_LIB_NAME)
endif()
endif()
# Populate the include directories
get_target_property(GINKGO_LIBS_INTERFACE_INCS "${_libs}"
INTERFACE_INCLUDE_DIRECTORIES)
foreach(_incs ${GINKGO_LIBS_INTERFACE_INCS})
filter_generator_expressions("${_incs}" GINKGO_INTERFACE_INC_FILTERED)
if (GINKGO_INTERFACE_INC_FILTERED AND NOT
"-I${GINKGO_INTERFACE_INC_FILTERED}" IN_LIST GINKGO_INTERFACE_CFLAGS_FOUND)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "-I${GINKGO_INTERFACE_INC_FILTERED}")
unset(GINKGO_INTERFACE_LIBS_LINK_FLAGS)

# Get the imported library
get_target_property(_lib_type "${_lib}" TYPE)
get_target_property(_lib_imported "${_lib}" IMPORTED)
if (_lib_imported AND NOT ${_lib_type} STREQUAL "INTERFACE_LIBRARY")
get_target_property(GINKGO_LIBS_IMPORTED_LIBS "${_lib}" IMPORTED_LOCATION_RELEASE)
if (NOT GINKGO_LIBS_IMPORTED_LIBS)
get_target_property(GINKGO_LIBS_IMPORTED_LIBS "${_lib}" IMPORTED_LOCATION)
endif()
if (GINKGO_LIBS_IMPORTED_LIBS)
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${GINKGO_LIBS_IMPORTED_LIBS}")
endif()
unset(GINKGO_LIBS_IMPORTED_LIBS)
endif()
endforeach()
unset(_lib_type)
unset(_lib_imported)

# Populate the compiler options and definitions if needed
get_target_property(GINKGO_LIBS_INTERFACE_DEFS "${_libs}"
INTERFACE_COMPILE_DEFINITIONS)
if (GINKGO_LIBS_INTERFACE_DEFS)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "${GINKGO_LIBS_INTERFACE_DEFS}")
endif()
get_target_property(GINKGO_LIBS_INTERFACE_OPTS "${_libs}"
INTERFACE_COMPILE_OPTIONS)
filter_generator_expressions("${GINKGO_LIBS_INTERFACE_OPTS}" GINKGO_LIBS_INTERFACE_OPTS_FILTERED)
if (GINKGO_LIBS_INTERFACE_OPTS)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "${GINKGO_LIBS_INTERFACE_OPTS_FILTERED}")
endif()
# Populate the include directories
get_target_property(GINKGO_LIBS_INTERFACE_INCS "${_lib}" INTERFACE_INCLUDE_DIRECTORIES)
foreach(_incs ${GINKGO_LIBS_INTERFACE_INCS})
filter_generator_expressions("${_incs}" GINKGO_INTERFACE_INC_FILTERED)
if (GINKGO_INTERFACE_INC_FILTERED AND NOT
"-I${GINKGO_INTERFACE_INC_FILTERED}" IN_LIST GINKGO_INTERFACE_CFLAGS_FOUND)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "-I${GINKGO_INTERFACE_INC_FILTERED}")
endif()
unset(GINKGO_INTERFACE_INC_FILTERED)
endforeach()
unset(GINKGO_LIBS_INTERFACE_INCS)

# Populate the compiler options and definitions if needed
get_target_property(GINKGO_LIBS_INTERFACE_DEFS "${_lib}" INTERFACE_COMPILE_DEFINITIONS)
if (GINKGO_LIBS_INTERFACE_DEFS)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "${GINKGO_LIBS_INTERFACE_DEFS}")
endif()
unset(GINKGO_LIBS_INTERFACE_DEFS)

# Keep recursing through the libraries
get_target_property(GINKGO_LIBS_INTERFACE_LIBS "${_libs}"
INTERFACE_LINK_LIBRARIES)
# removing $<LINK_ONLY:>
list(TRANSFORM GINKGO_LIBS_INTERFACE_LIBS REPLACE "\\$<LINK_ONLY:(.*)>" "\\1")
ginkgo_interface_libraries_recursively("${GINKGO_LIBS_INTERFACE_LIBS}")
elseif(EXISTS "${_libs}")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${_libs}")
elseif("${_libs}" STREQUAL "${CMAKE_DL_LIBS}")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "-l${_libs}")
get_target_property(GINKGO_LIBS_INTERFACE_OPTS "${_lib}" INTERFACE_COMPILE_OPTIONS)
filter_generator_expressions("${GINKGO_LIBS_INTERFACE_OPTS}" GINKGO_LIBS_INTERFACE_OPTS_FILTERED)
if (GINKGO_LIBS_INTERFACE_OPTS)
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "${GINKGO_LIBS_INTERFACE_OPTS_FILTERED}")
endif()
unset(GINKGO_LIBS_INTERFACE_OPTS)

# Keep recursing through the libraries
get_target_property(GINKGO_LIBS_INTERFACE_LIBS "${_lib}" INTERFACE_LINK_LIBRARIES)
# removing $<LINK_ONLY:>
list(TRANSFORM GINKGO_LIBS_INTERFACE_LIBS REPLACE "\\$<LINK_ONLY:(.*)>" "\\1")
ginkgo_interface_libraries_recursively("${GINKGO_LIBS_INTERFACE_LIBS}")
unset(GINKGO_LIBS_INTERFACE_LIBS)
elseif(EXISTS "${_lib}")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "${_lib}")
elseif("${_lib}" STREQUAL "${CMAKE_DL_LIBS}")
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "-l${_lib}")
endif()
endif()
unset(_lib)
endforeach()
endmacro()

macro(ginkgo_interface_information)
set(GINKGO_INTERFACE_LINK_FLAGS "-L${CMAKE_INSTALL_FULL_LIBDIR}")
macro(ginkgo_pkg_information)
set(GINKGO_INTERFACE_LINK_FLAGS "-L\\\${prefix}/${CMAKE_INSTALL_LIBDIR}")
unset(GINKGO_INTERFACE_LIBS_FOUND)
unset(GINKGO_INTERFACE_CFLAGS_FOUND)
# Prepare recursively populated library list
list(APPEND GINKGO_INTERFACE_LIBS_FOUND "-lginkgo$<$<CONFIG:Debug>:${CMAKE_DEBUG_POSTFIX}>")
# Prepare recursively populated include directory list
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND
"-I${CMAKE_INSTALL_FULL_INCLUDEDIR}")
list(APPEND GINKGO_INTERFACE_CFLAGS_FOUND "-I\\\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")

# Call the recursive interface libraries macro
get_target_property(GINKGO_INTERFACE_LINK_LIBRARIES ginkgo INTERFACE_LINK_LIBRARIES)
ginkgo_interface_libraries_recursively("${GINKGO_INTERFACE_LINK_LIBRARIES}")
# Format and store the interface libraries found
# remove duplicates on the reversed list to keep the dependency in the end of list.
list(REVERSE GINKGO_INTERFACE_LIBS_FOUND)
list(REMOVE_DUPLICATES GINKGO_INTERFACE_LIBS_FOUND)
list(REVERSE GINKGO_INTERFACE_LIBS_FOUND)
list(REMOVE_ITEM GINKGO_INTERFACE_LIBS_FOUND "")
# keep it as list
set(GINKGO_INTERFACE_LINK_FLAGS
${GINKGO_INTERFACE_LINK_FLAGS} ${GINKGO_INTERFACE_LIBS_FOUND})
set(GINKGO_INTERFACE_LINK_FLAGS ${GINKGO_INTERFACE_LINK_FLAGS} ${GINKGO_INTERFACE_LIBS_FOUND})
unset(GINKGO_INTERFACE_LIBS_FOUND)
# Format and store the interface cflags found
list(REMOVE_DUPLICATES GINKGO_INTERFACE_CFLAGS_FOUND)
list(REMOVE_ITEM GINKGO_INTERFACE_CFLAGS_FOUND "")
# Keep it as list
set(GINKGO_INTERFACE_CXX_FLAGS ${GINKGO_INTERFACE_CFLAGS_FOUND})
unset(GINKGO_INTERFACE_CFLAGS_FOUND)
endmacro(ginkgo_interface_information)
endmacro(ginkgo_pkg_information)

macro(ginkgo_git_information)
if(EXISTS "${Ginkgo_SOURCE_DIR}/.git")
Expand Down
Loading

0 comments on commit 45692bd

Please sign in to comment.