# COPYRIGHT (c) 2016 Obsidian Research Corporation.
# Licensed under BSD (MIT variant) or GPLv2. See COPYING.
# Helper functions for use in the sub CMakeLists files to make them simpler
# and more uniform.
# Global list of tuples of (SHARED STATIC MAP) library target names
set(RDMA_STATIC_LIBS "" CACHE INTERNAL "Doc" FORCE)
# Global list of tuples of (PROVIDER_NAME LIB_NAME)
set(RDMA_PROVIDER_LIST "" CACHE INTERNAL "Doc" FORCE)
set(COMMON_LIBS_PIC ccan_pic rdma_util_pic)
set(COMMON_LIBS ccan rdma_util)
function(rdma_public_static_lib SHLIB STATICLIB VERSION_SCRIPT)
if (NOT IS_ABSOLUTE ${VERSION_SCRIPT})
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${VERSION_SCRIPT}")
endif()
set_target_properties(${STATICLIB} PROPERTIES
OUTPUT_NAME ${SHLIB}
ARCHIVE_OUTPUT_DIRECTORY "${BUILD_STATIC_LIB}")
target_compile_definitions(${STATICLIB} PRIVATE _STATIC_LIBRARY_BUILD_=1)
list(APPEND RDMA_STATIC_LIBS ${SHLIB} ${STATICLIB} ${VERSION_SCRIPT})
set(RDMA_STATIC_LIBS "${RDMA_STATIC_LIBS}" CACHE INTERNAL "")
endfunction()
function(rdma_make_dir DDIR)
if(NOT EXISTS "${DDIR}/")
execute_process(COMMAND "${CMAKE_COMMAND}" "-E" "make_directory"
"${DDIR}" RESULT_VARIABLE retcode)
if(NOT "${retcode}" STREQUAL "0")
message(FATAL_ERROR "Failed to create directory ${DDIR}")
endif()
endif()
endfunction()
# Create a symlink at filename DEST
# If the directory containing DEST does not exist then it is created
# automatically.
function(rdma_create_symlink LINK_CONTENT DEST)
if(NOT LINK_CONTENT)
message(FATAL_ERROR "Failed to provide LINK_CONTENT")
endif()
# Make sure the directory exists, cmake doesn't create target DESTINATION
# directories until everything is finished, do it manually here if necessary
if(CMAKE_VERSION VERSION_LESS "2.8.12")
get_filename_component(DDIR "${DEST}" PATH)
else()
get_filename_component(DDIR "${DEST}" DIRECTORY)
endif()
rdma_make_dir("${DDIR}")
# Newer versions of cmake can use "${CMAKE_COMMAND}" "-E" "create_symlink"
# however it is broken weirdly on older versions.
execute_process(COMMAND "ln" "-Tsf"
"${LINK_CONTENT}" "${DEST}" RESULT_VARIABLE retcode)
if(NOT "${retcode}" STREQUAL "0")
message(FATAL_ERROR "Failed to create symlink in ${DEST}")
endif()
endfunction()
# Install a symlink during 'make install'
function(rdma_install_symlink LINK_CONTENT DEST)
# Create a link in the build tree with the right content
get_filename_component(FN "${DEST}" NAME)
rdma_create_symlink("${LINK_CONTENT}" "${CMAKE_CURRENT_BINARY_DIR}/${FN}")
# Have cmake install it. Doing it this way lets cpack work if we ever wish
# to use that.
get_filename_component(DIR "${DEST}" PATH)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${FN}"
DESTINATION "${DIR}")
endfunction()
# Wrapper for install() that runs the single file through configure_file first.
# This only works with the basic single file install(FILE file ARGS..) pattern
function(rdma_subst_install ARG1 file)
if (NOT "${ARG1}" STREQUAL "FILES")
message(FATAL_ERROR "Bad use of rdma_subst_install")
endif()
configure_file("${file}" "${CMAKE_CURRENT_BINARY_DIR}/${file}" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${file}" ${ARGN})
endfunction()
# Modify shared library target DEST to use VERSION_SCRIPT as the linker map file
function(rdma_set_library_map DEST VERSION_SCRIPT)
if (NOT IS_ABSOLUTE ${VERSION_SCRIPT})
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${VERSION_SCRIPT}")
endif()
set_property(TARGET ${DEST} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script,${VERSION_SCRIPT}")
# NOTE: This won't work with ninja prior to cmake 3.4
set_property(TARGET ${DEST} APPEND_STRING PROPERTY
LINK_DEPENDS ${VERSION_SCRIPT})
endfunction()
# Basic function to produce a standard libary with a GNU LD version script.
function(rdma_library DEST VERSION_SCRIPT SOVERSION VERSION)
# Create a static library
if (ENABLE_STATIC)
add_library(${DEST}-static STATIC ${ARGN})
target_link_libraries(${DEST}-static LINK ${COMMON_LIBS})
rdma_public_static_lib(${DEST} ${DEST}-static ${VERSION_SCRIPT})
endif()
# Create a shared library
add_library(${DEST} SHARED ${ARGN})
rdma_set_library_map(${DEST} ${VERSION_SCRIPT})
target_link_libraries(${DEST} LINK_PRIVATE ${COMMON_LIBS_PIC})
set_target_properties(${DEST} PROPERTIES
SOVERSION ${SOVERSION}
VERSION ${VERSION}
LIBRARY_OUTPUT_DIRECTORY "${BUILD_LIB}")
install(TARGETS ${DEST} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endfunction()
# Create a special provider with exported symbols in it The shared provider
# exists as a normal system library with the normal shared library SONAME and
# other convections. The system library is symlinked into the
# VERBS_PROVIDER_DIR so it can be dlopened as a provider as well.
function(rdma_shared_provider DEST VERSION_SCRIPT SOVERSION VERSION)
# Installed driver file
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${DEST}.driver" "driver ${DEST}\n")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${DEST}.driver" DESTINATION "${CONFIG_DIR}")
# Uninstalled driver file
file(MAKE_DIRECTORY "${BUILD_ETC}/libibverbs.d/")
file(WRITE "${BUILD_ETC}/libibverbs.d/${DEST}.driver" "driver ${BUILD_LIB}/lib${DEST}\n")
list(APPEND RDMA_PROVIDER_LIST ${DEST} ${DEST})
set(RDMA_PROVIDER_LIST "${RDMA_PROVIDER_LIST}" CACHE INTERNAL "")
# Create a static provider library
if (ENABLE_STATIC)
add_library(${DEST}-static STATIC ${ARGN})
rdma_public_static_lib(${DEST} ${DEST}-static ${VERSION_SCRIPT})
endif()
# Create the plugin shared library
add_library(${DEST} SHARED ${ARGN})
rdma_set_library_map(${DEST} ${VERSION_SCRIPT})
target_link_libraries(${DEST} LINK_PRIVATE ${COMMON_LIBS_PIC})
target_link_libraries(${DEST} LINK_PRIVATE ibverbs)
target_link_libraries(${DEST} LINK_PRIVATE ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(${DEST} PROPERTIES
SOVERSION ${SOVERSION}
VERSION ${VERSION}
LIBRARY_OUTPUT_DIRECTORY "${BUILD_LIB}")
install(TARGETS ${DEST} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
# Compute a relative symlink from VERBS_PROVIDER_DIR to LIBDIR
execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/buildlib/relpath
"${CMAKE_INSTALL_FULL_LIBDIR}/lib${DEST}.so.${VERSION}"
"${VERBS_PROVIDER_DIR}"
OUTPUT_VARIABLE DEST_LINK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE retcode)
if(NOT "${retcode}" STREQUAL "0")
message(FATAL_ERROR "Unable to run buildlib/relpath, do you have python?")
endif()
rdma_install_symlink("${DEST_LINK_PATH}" "${VERBS_PROVIDER_DIR}/lib${DEST}${IBVERBS_PROVIDER_SUFFIX}")
rdma_create_symlink("lib${DEST}.so.${VERSION}" "${BUILD_LIB}/lib${DEST}${IBVERBS_PROVIDER_SUFFIX}")
endfunction()
# Create a provider shared library for libibverbs
function(rdma_provider DEST)
# Installed driver file
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${DEST}.driver" "driver ${DEST}\n")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${DEST}.driver" DESTINATION "${CONFIG_DIR}")
# Uninstalled driver file
file(MAKE_DIRECTORY "${BUILD_ETC}/libibverbs.d/")
file(WRITE "${BUILD_ETC}/libibverbs.d/${DEST}.driver" "driver ${BUILD_LIB}/lib${DEST}\n")
list(APPEND RDMA_PROVIDER_LIST ${DEST} "${DEST}-rdmav${IBVERBS_PABI_VERSION}")
set(RDMA_PROVIDER_LIST "${RDMA_PROVIDER_LIST}" CACHE INTERNAL "")
# Create a static provider library
if (ENABLE_STATIC)
add_library(${DEST} STATIC ${ARGN})
rdma_public_static_lib("${DEST}-rdmav${IBVERBS_PABI_VERSION}" ${DEST} ${BUILDLIB}/provider.map)
endif()
# Create the plugin shared library
set(DEST "${DEST}-rdmav${IBVERBS_PABI_VERSION}")
add_library(${DEST} MODULE ${ARGN})
# Even though these are modules we still want to use Wl,--no-undefined
set_target_properties(${DEST} PROPERTIES LINK_FLAGS ${CMAKE_SHARED_LINKER_FLAGS})
rdma_set_library_map(${DEST} ${BUILDLIB}/provider.map)
target_link_libraries(${DEST} LINK_PRIVATE ${COMMON_LIBS_PIC})
target_link_libraries(${DEST} LINK_PRIVATE ibverbs)
target_link_libraries(${DEST} LINK_PRIVATE ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(${DEST} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${BUILD_LIB}")
# Provider Plugins do not use SONAME versioning, there is no reason to
# create the usual symlinks.
if (VERBS_PROVIDER_DIR)
install(TARGETS ${DEST} DESTINATION "${VERBS_PROVIDER_DIR}")
else()
install(TARGETS ${DEST} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
# FIXME: This symlink is provided for compat with the old build, but it
# never should have existed in the first place, nothing should use this
# name, we can probably remove it.
rdma_install_symlink("lib${DEST}${IBVERBS_PROVIDER_SUFFIX}" "${CMAKE_INSTALL_LIBDIR}/lib${DEST}.so")
endif()
endfunction()
# Create an installed executable
function(rdma_executable EXEC)
add_executable(${EXEC} ${ARGN})
target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS})
set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}")
install(TARGETS ${EXEC} DESTINATION "${CMAKE_INSTALL_BINDIR}")
endfunction()
# Create an installed executable (under sbin)
function(rdma_sbin_executable EXEC)
add_executable(${EXEC} ${ARGN})
target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS})
set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}")
install(TARGETS ${EXEC} DESTINATION "${CMAKE_INSTALL_SBINDIR}")
endfunction()
# Create an test executable (not-installed)
function(rdma_test_executable EXEC)
add_executable(${EXEC} ${ARGN})
target_link_libraries(${EXEC} LINK_PRIVATE ${COMMON_LIBS})
set_target_properties(${EXEC} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_BIN}")
endfunction()
# Finalize the setup of the static libraries by copying the meta information
# from the shared to static and setting up the static builder
function(rdma_finalize_libs)
list(LENGTH RDMA_STATIC_LIBS LEN)
if (LEN LESS 3)
return()
endif()
math(EXPR LEN ${LEN}-1)
foreach(I RANGE 0 ${LEN} 3)
list(GET RDMA_STATIC_LIBS ${I} SHARED)
math(EXPR I ${I}+1)
list(GET RDMA_STATIC_LIBS ${I} STATIC)
math(EXPR I ${I}+1)
list(GET RDMA_STATIC_LIBS ${I} MAP)
# PUBLIC libraries
set(LIBS "")
get_property(TMP TARGET ${SHARED} PROPERTY INTERFACE_LINK_LIBRARIES SET)
if (TMP)
get_target_property(TMP ${SHARED} INTERFACE_LINK_LIBRARIES)
set_target_properties(${STATIC} PROPERTIES INTERFACE_LINK_LIBRARIES "${TMP}")
set(LIBS "${TMP}")
endif()
# PRIVATE libraries
get_property(TMP TARGET ${SHARED} PROPERTY LINK_LIBRARIES SET)
if (TMP)
get_target_property(TMP ${SHARED} LINK_LIBRARIES)
set_target_properties(${STATIC} PROPERTIES LINK_LIBRARIES "${TMP}")
list(APPEND LIBS "${TMP}")
endif()
set(ARGS ${ARGS} --map "${MAP}" --lib "$<TARGET_FILE:${STATIC}>")
set(DEPENDS ${DEPENDS} ${STATIC} ${MAP})
get_target_property(TMP ${STATIC} OUTPUT_NAME)
set(OUTPUTS ${OUTPUTS} "${BUILD_LIB}/lib${TMP}.a")
install(FILES "${BUILD_LIB}/lib${TMP}.a" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endforeach()
foreach(STATIC ${COMMON_LIBS})
set(ARGS ${ARGS} --internal_lib "$<TARGET_FILE:${STATIC}>")
set(DEPENDS ${DEPENDS} ${STATIC})
endforeach()
add_custom_command(
OUTPUT ${OUTPUTS}
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/buildlib/sanitize_static_lib.py"
--version ${PACKAGE_VERSION}
--ar "${CMAKE_AR}" --nm "${CMAKE_NM}" --objcopy "${CMAKE_OBJCOPY}" ${ARGS}
DEPENDS ${DEPENDS} "${CMAKE_SOURCE_DIR}/buildlib/sanitize_static_lib.py"
COMMENT "Building distributable static libraries"
VERBATIM)
add_custom_target("make_static" ALL DEPENDS ${OUTPUTS})
endfunction()
# Generate a pkg-config file
function(rdma_pkg_config PC_LIB_NAME PC_REQUIRES_PRIVATE PC_LIB_PRIVATE)
set(PC_LIB_NAME "${PC_LIB_NAME}")
set(PC_LIB_PRIVATE "${PC_LIB_PRIVATE}")
set(PC_REQUIRES_PRIVATE "${PC_REQUIRES_PRIVATE}")
get_target_property(PC_VERSION ${PC_LIB_NAME} VERSION)
# With IN_PLACE=1 the install step is not run, so generate the file in the build dir
if (IN_PLACE)
set(PC_RPATH "-Wl,-rpath,\${libdir}")
endif()
configure_file(${BUILDLIB}/template.pc.in ${BUILD_LIB}/pkgconfig/lib${PC_LIB_NAME}.pc @ONLY)
if (NOT IN_PLACE)
install(FILES ${BUILD_LIB}/pkgconfig/lib${PC_LIB_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
endfunction()