Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions cmake/link_vt.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,9 @@ function(link_target_with_vt)
message(STATUS "link_target_with_vt: fmt=${ARG_LINK_FMT}")
endif()

if(${vt_external_fmt})
target_link_libraries(
${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} fmt::fmt
)
else()
target_link_libraries(
${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${FMT_LIBRARY}
)
endif()
target_link_libraries(
${ARG_TARGET} PUBLIC ${ARG_BUILD_TYPE} ${FMT_LINK_TARGET}
)

endif()

Expand Down
22 changes: 17 additions & 5 deletions cmake/load_bundled_libraries.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endif()
# CLI11 always included in the build
add_subdirectory(${PROJECT_LIB_DIR}/CLI)

# use included fmt or external one
# Use an external fmt package or configure VT's shared DARMA fmt provider.
if(${vt_external_fmt})
# user should provide 'fmt_DIR' or 'fmt_ROOT' to CMake (unless fmt is installed in system libs)
if(fmt_ROOT)
Expand All @@ -31,11 +31,23 @@ if(${vt_external_fmt})
message(STATUS "vt_external_fmt = ON but neither fmt_DIR nor fmt_ROOT is provided!")
endif()
find_package(fmt 10.2.1 REQUIRED)

set(FMT_LIBRARY "")
set(FMT_LINK_TARGET fmt::fmt)
set(vt_uses_parent_fmt 0)
else()
set(FMT_LIBRARY fmt)
add_subdirectory(${PROJECT_LIB_DIR}/fmt)
set_darma_compiler_flags(${FMT_LIBRARY})
include(setup_fmt)
darma_setup_fmt(
SOURCE_DIR "${PROJECT_LIB_DIR}/fmt"
VENDORED_TARGET fmt
OUT_LIBRARY FMT_LIBRARY
OUT_LINK_TARGET FMT_LINK_TARGET
POST_ADD_COMMAND set_darma_compiler_flags
)
if(FMT_LIBRARY)
set(vt_uses_parent_fmt 0)
else()
set(vt_uses_parent_fmt 1)
endif()
endif()

# yaml-cpp always included in the build
Expand Down
174 changes: 174 additions & 0 deletions cmake/setup_fmt.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
include_guard(GLOBAL)

# Configure one compiled fmt provider across a hierarchy of DARMA projects.
#
# The first project in a hierarchy builds its vendored fmt. Later projects
# reuse that fmt::fmt target and only contribute their local include layout
# (for example fmt-vt, fmt, or fmt-lb). Exact FMT_VERSION equality is required
# so local headers never call into an incompatible compiled fmt implementation.
#
# Copy this file into each repository and replace add_subdirectory(fmt) with:
#
# include(cmake/setup_fmt.cmake)
# darma_setup_fmt(
# SOURCE_DIR lib/fmt
# VENDORED_TARGET fmt
# OUT_LIBRARY FMT_LIBRARY
# OUT_LINK_TARGET FMT_LINK_TARGET
# )
#
# VT, comm, and loc use lib/fmt + fmt; LB uses tpl/fmt + fmt-lb.
# Optional POST_ADD_COMMAND names a project function which is called only when
# the current project owns and compiles the vendored target.
function(darma_setup_fmt)
cmake_parse_arguments(
PARSE_ARGV 0
DARMA_FMT
""
"SOURCE_DIR;VENDORED_TARGET;OUT_LIBRARY;OUT_LINK_TARGET;POST_ADD_COMMAND"
""
)

foreach(required_arg
SOURCE_DIR VENDORED_TARGET OUT_LIBRARY OUT_LINK_TARGET)
if(NOT DARMA_FMT_${required_arg})
message(FATAL_ERROR "darma_setup_fmt requires ${required_arg}")
endif()
endforeach()

if(IS_ABSOLUTE "${DARMA_FMT_SOURCE_DIR}")
set(fmt_source_dir "${DARMA_FMT_SOURCE_DIR}")
else()
get_filename_component(
fmt_source_dir
"${DARMA_FMT_SOURCE_DIR}"
ABSOLUTE
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
)
endif()

file(GLOB fmt_base_headers "${fmt_source_dir}/include/*/base.h")
list(LENGTH fmt_base_headers fmt_base_header_count)
if(NOT fmt_base_header_count EQUAL 1)
message(
FATAL_ERROR
"Expected one fmt base.h below ${fmt_source_dir}/include, found "
"${fmt_base_header_count}"
)
endif()

list(GET fmt_base_headers 0 fmt_base_header)
file(STRINGS
"${fmt_base_header}"
fmt_version_line
REGEX "^# *define FMT_VERSION [0-9]+"
LIMIT_COUNT 1
)
if(NOT fmt_version_line MATCHES "FMT_VERSION +([0-9]+)")
message(FATAL_ERROR "Could not read FMT_VERSION from ${fmt_base_header}")
endif()
set(local_fmt_version "${CMAKE_MATCH_1}")

# The first DARMA project in the CMake hierarchy owns fmt. It need not be
# the top-level CMake project: consumers commonly add VT as a subdirectory
# without configuring fmt themselves (for example vt-sample-project).
if(NOT TARGET fmt::fmt)
# fmt is compiled as ordinary C++20 and its module target is disabled by
# the caller. Prevent CMP0155 from requiring a compiler dependency scanner
# (for example clang-scan-deps) for these non-module sources.
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
add_subdirectory("${fmt_source_dir}")

if(NOT TARGET ${DARMA_FMT_VENDORED_TARGET})
message(
FATAL_ERROR
"${fmt_source_dir} did not create target "
"'${DARMA_FMT_VENDORED_TARGET}'"
)
endif()
# VT and comm already expose fmt::fmt. LB's renamed vendored target is
# fmt-lb, so supply the common provider alias here when it is absent.
if(NOT TARGET fmt::fmt)
add_library(fmt::fmt ALIAS ${DARMA_FMT_VENDORED_TARGET})
endif()

if(DARMA_FMT_POST_ADD_COMMAND)
if(NOT COMMAND ${DARMA_FMT_POST_ADD_COMMAND})
message(
FATAL_ERROR
"Unknown POST_ADD_COMMAND: ${DARMA_FMT_POST_ADD_COMMAND}"
)
endif()
cmake_language(
CALL ${DARMA_FMT_POST_ADD_COMMAND} ${DARMA_FMT_VENDORED_TARGET}
)
endif()

set_property(
TARGET ${DARMA_FMT_VENDORED_TARGET}
PROPERTY INTERFACE_DARMA_FMT_VERSION "${local_fmt_version}"
)
set(fmt_owned_library "${DARMA_FMT_VENDORED_TARGET}")
message(
STATUS
"${PROJECT_NAME}: building vendored fmt ${local_fmt_version}"
)
else()
get_target_property(fmt_provider_target fmt::fmt ALIASED_TARGET)
if(NOT fmt_provider_target)
set(fmt_provider_target fmt::fmt)
endif()
get_target_property(
parent_fmt_version
${fmt_provider_target}
INTERFACE_DARMA_FMT_VERSION
)
if(NOT parent_fmt_version)
message(
FATAL_ERROR
"The parent fmt::fmt target was not configured by setup_fmt.cmake; "
"its version cannot be verified."
)
endif()
if(NOT local_fmt_version STREQUAL parent_fmt_version)
message(
FATAL_ERROR
"fmt version mismatch: ${PROJECT_NAME} has ${local_fmt_version}, "
"but the parent provider has ${parent_fmt_version}."
)
endif()

# The projects intentionally use different include directory names while
# sharing fmt's ABI. Make this project's headers visible through the one
# parent provider without installing or compiling another fmt library.
target_include_directories(
${fmt_provider_target} INTERFACE
$<BUILD_INTERFACE:${fmt_source_dir}/include>
)

# The provider may install a different header layout (for example fmt-lb).
# Consumers of this project's installed headers still need its local fmt
# include names, even though they link to the parent's compiled library.
if(FMT_INC_DIR)
set(fmt_install_include_dir "${FMT_INC_DIR}")
else()
include(GNUInstallDirs)
set(fmt_install_include_dir "${CMAKE_INSTALL_INCLUDEDIR}")
endif()
install(
DIRECTORY "${fmt_source_dir}/include/"
DESTINATION "${fmt_install_include_dir}"
COMPONENT fmt-core
FILES_MATCHING PATTERN "*.h"
)

set(fmt_owned_library "")
message(
STATUS
"${PROJECT_NAME}: reusing parent fmt ${parent_fmt_version}"
)
endif()

set(${DARMA_FMT_OUT_LIBRARY} "${fmt_owned_library}" PARENT_SCOPE)
set(${DARMA_FMT_OUT_LINK_TARGET} fmt::fmt PARENT_SCOPE)
endfunction()
4 changes: 3 additions & 1 deletion cmake/trace_only_functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ function(create_trace_only_target)
CONFIGURATIONS ${build_type_list}
)

install(TARGETS ${FMT_LIBRARY} EXPORT ${VT_TRACE_LIB})
if(FMT_LIBRARY)
install(TARGETS ${FMT_LIBRARY} EXPORT ${VT_TRACE_LIB})
endif()

export(
TARGETS ${VT_TRACE_LIB}
Expand Down
2 changes: 1 addition & 1 deletion cmake/vtConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ endif()
set (VT_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/include")
set (VT_CXX_COMPILER "@CMAKE_CXX_COMPILER@")

if (@vt_external_fmt@)
if (@vt_external_fmt@ OR @vt_uses_parent_fmt@)
set (fmt_DIR @fmt_DIR@)
set (fmt_ROOT @fmt_ROOT@)
find_dependency(fmt REQUIRED HINTS @fmt_DIR@ @fmt_ROOT@)
Expand Down
4 changes: 3 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,9 @@ install(

install(TARGETS ${BROTLI_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})
install(TARGETS ${ENG_FORMAT_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})
install(TARGETS ${FMT_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})
if(FMT_LIBRARY)
install(TARGETS ${FMT_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})
endif()
install(TARGETS ${YAMLCPP_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})
install(TARGETS ${JSON_LIBRARY} EXPORT ${VIRTUAL_TRANSPORT_LIBRARY})

Expand Down
Loading