# get header files; only needed by CMake generators,
# e.g., for creating proper Xcode projects
file(GLOB_RECURSE LIBCAF_CORE_HDRS "caf/*.hpp")

# extend the consistency-check target for enum to_string implementations
add_enum_consistency_check("caf/sec.hpp" "src/sec_strings.cpp")
add_enum_consistency_check("caf/pec.hpp" "src/pec_strings.cpp")
add_enum_consistency_check("caf/stream_priority.hpp"
                           "src/stream_priority_strings.cpp")
add_enum_consistency_check("caf/exit_reason.hpp"
                           "src/exit_reason_strings.cpp")
add_enum_consistency_check("caf/invoke_message_result.hpp"
                           "src/invoke_msg_result_strings.cpp")
add_enum_consistency_check("caf/message_priority.hpp"
                           "src/message_priority_strings.cpp")
add_enum_consistency_check("caf/intrusive/inbox_result.hpp"
                           "src/intrusive/inbox_result_strings.cpp")
add_enum_consistency_check("caf/intrusive/task_result.hpp"
                           "src/intrusive/task_result_strings.cpp")

# list cpp files excluding platform-dependent files
set(LIBCAF_CORE_SRCS
  src/abstract_actor.cpp
  src/abstract_channel.cpp
  src/abstract_composable_behavior.cpp
  src/abstract_group.cpp
  src/actor.cpp
  src/actor_addr.cpp
  src/actor_clock.cpp
  src/actor_companion.cpp
  src/actor_config.cpp
  src/actor_control_block.cpp
  src/actor_ostream.cpp
  src/actor_pool.cpp
  src/actor_profiler.cpp
  src/actor_proxy.cpp
  src/actor_registry.cpp
  src/actor_system.cpp
  src/actor_system_config.cpp
  src/atom.cpp
  src/attachable.cpp
  src/behavior.cpp
  src/binary_deserializer.cpp
  src/blocking_actor.cpp
  src/config_option.cpp
  src/config_option_adder.cpp
  src/config_option_set.cpp
  src/config_value.cpp
  src/decorator/sequencer.cpp
  src/decorator/splitter.cpp
  src/default_attachable.cpp
  src/defaults.cpp
  src/deserializer.cpp
  src/detail/abstract_worker.cpp
  src/detail/abstract_worker_hub.cpp
  src/detail/append_hex.cpp
  src/detail/append_percent_encoded.cpp
  src/detail/behavior_impl.cpp
  src/detail/behavior_stack.cpp
  src/detail/blocking_behavior.cpp
  src/detail/concatenated_tuple.cpp
  src/detail/decorated_tuple.cpp
  src/detail/dynamic_message_data.cpp
  src/detail/fnv_hash.cpp
  src/detail/get_mac_addresses.cpp
  src/detail/get_process_id.cpp
  src/detail/get_root_uuid.cpp
  src/detail/ini_consumer.cpp
  src/detail/invoke_result_visitor.cpp
  src/detail/merged_tuple.cpp
  src/detail/message_data.cpp
  src/detail/parse.cpp
  src/detail/parser/chars.cpp
  src/detail/pretty_type_name.cpp
  src/detail/private_thread.cpp
  src/detail/ripemd_160.cpp
  src/detail/serialized_size.cpp
  src/detail/set_thread_name.cpp
  src/detail/shared_spinlock.cpp
  src/detail/simple_actor_clock.cpp
  src/detail/stringification_inspector.cpp
  src/detail/sync_request_bouncer.cpp
  src/detail/test_actor_clock.cpp
  src/detail/thread_safe_actor_clock.cpp
  src/detail/tick_emitter.cpp
  src/detail/try_match.cpp
  src/detail/uri_impl.cpp
  src/downstream_manager.cpp
  src/downstream_manager_base.cpp
  src/duration.cpp
  src/error.cpp
  src/event_based_actor.cpp
  src/execution_unit.cpp
  src/exit_reason.cpp
  src/exit_reason_strings.cpp
  src/forwarding_actor_proxy.cpp
  src/group.cpp
  src/group_manager.cpp
  src/group_module.cpp
  src/inbound_path.cpp
  src/intrusive/inbox_result_strings.cpp
  src/intrusive/task_result_strings.cpp
  src/invoke_msg_result_strings.cpp
  src/ipv4_address.cpp
  src/ipv4_endpoint.cpp
  src/ipv4_subnet.cpp
  src/ipv6_address.cpp
  src/ipv6_endpoint.cpp
  src/ipv6_subnet.cpp
  src/local_actor.cpp
  src/logger.cpp
  src/mailbox_element.cpp
  src/make_config_option.cpp
  src/match_case.cpp
  src/memory_managed.cpp
  src/message.cpp
  src/message_builder.cpp
  src/message_handler.cpp
  src/message_priority_strings.cpp
  src/message_view.cpp
  src/monitorable_actor.cpp
  src/node_id.cpp
  src/outbound_path.cpp
  src/pec.cpp
  src/pec_strings.cpp
  src/policy/downstream_messages.cpp
  src/policy/unprofiled.cpp
  src/policy/work_sharing.cpp
  src/policy/work_stealing.cpp
  src/proxy_registry.cpp
  src/raise_error.cpp
  src/raw_event_based_actor.cpp
  src/ref_counted.cpp
  src/replies_to.cpp
  src/response_promise.cpp
  src/resumable.cpp
  src/rtti_pair.cpp
  src/runtime_settings_map.cpp
  src/scheduled_actor.cpp
  src/scheduler/abstract_coordinator.cpp
  src/scheduler/test_coordinator.cpp
  src/scoped_actor.cpp
  src/scoped_execution_unit.cpp
  src/sec.cpp
  src/sec_strings.cpp
  src/serializer.cpp
  src/settings.cpp
  src/skip.cpp
  src/stream_aborter.cpp
  src/stream_manager.cpp
  src/stream_priority_strings.cpp
  src/string_algorithms.cpp
  src/string_view.cpp
  src/term.cpp
  src/thread_hook.cpp
  src/timestamp.cpp
  src/type_erased_tuple.cpp
  src/type_erased_value.cpp
  src/uniform_type_info_map.cpp
  src/uri.cpp
  src/uri_builder.cpp
)

# configure build_config.hpp header
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/build_config.hpp.in"
               "${CMAKE_CURRENT_BINARY_DIR}/caf/detail/build_config.hpp"
               @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/caf/detail/build_config.hpp"
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/caf/detail)

list(APPEND LIBCAF_CORE_HDRS
  "${CMAKE_CURRENT_BINARY_DIR}/caf/detail/build_config.hpp")

add_custom_target(libcaf_core)

# build shared library if not compiling static only
if (NOT CAF_BUILD_STATIC_ONLY)
  add_library(libcaf_core_shared SHARED ${LIBCAF_CORE_SRCS} ${LIBCAF_CORE_HDRS})
  target_link_libraries(libcaf_core_shared ${CAF_EXTRA_LDFLAGS})
  target_include_directories(libcaf_core_shared PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:include>
  )
  set_target_properties(libcaf_core_shared
    PROPERTIES
    SOVERSION ${CAF_VERSION}
    VERSION ${CAF_LIB_VERSION}
    OUTPUT_NAME caf_core
  )
  install(TARGETS libcaf_core_shared
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )
  add_dependencies(libcaf_core_shared libcaf_core)
endif ()

# build static library only if --build-static or --build-static-only was set
if (CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
  add_library(libcaf_core_static STATIC ${LIBCAF_CORE_HDRS} ${LIBCAF_CORE_SRCS})
  target_link_libraries(libcaf_core_static ${CAF_EXTRA_LDFLAGS})
  target_include_directories(libcaf_core_static PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:include>
  )
  set_target_properties(libcaf_core_static PROPERTIES OUTPUT_NAME caf_core_static)
  install(TARGETS libcaf_core_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
  add_dependencies(libcaf_core_static libcaf_core)
endif ()

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/caf"
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
        FILES_MATCHING PATTERN "*.hpp"
)

# -- build unit tests ----------------------------------------------------------

if(CAF_NO_UNIT_TESTS)
  return()
endif()

add_executable(caf-core-test test/core-test.cpp)

target_include_directories(caf-core-test PRIVATE
                           "${CMAKE_CURRENT_SOURCE_DIR}/test")

if (CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
  target_link_libraries(caf-core-test libcaf_core_static  ${CAF_EXTRA_LDFLAGS})
else()
  target_link_libraries(caf-core-test libcaf_core_shared  ${CAF_EXTRA_LDFLAGS})
endif()

caf_add_test_suites(caf-core-test
  actor_clock
  actor_factory
  actor_lifetime
  actor_pool
  actor_profiler
  actor_registry
  actor_system_config
  actor_termination
  aout
  behavior
  blocking_actor
  broadcast_downstream_manager
  byte
  composition
  config_option
  config_option_set
  config_value
  config_value_adaptor
  constructor_attach
  continuous_streaming
  cow_tuple
  decorator.sequencer
  deep_to_string
  detached_actors
  detail.bounds_checker
  detail.ini_consumer
  detail.limited_vector
  detail.parse
  detail.parser.read_bool
  detail.parser.read_floating_point
  detail.parser.read_ini
  detail.parser.read_number
  detail.parser.read_number_or_timespan
  detail.parser.read_signed_integer
  detail.parser.read_string
  detail.parser.read_timespan
  detail.parser.read_unsigned_integer
  detail.ringbuffer
  detail.ripemd_160
  detail.serialized_size
  detail.tick_emitter
  detail.unique_function
  detail.unordered_flat_map
  dictionary
  dynamic_spawn
  expected
  function_view
  fused_downstream_manager
  handles
  inspector
  intrusive.drr_cached_queue
  intrusive.drr_queue
  intrusive.fifo_inbox
  intrusive.lifo_inbox
  intrusive.task_queue
  intrusive.wdrr_dynamic_multiplexed_queue
  intrusive.wdrr_fixed_multiplexed_queue
  intrusive_ptr
  ipv4_address
  ipv4_endpoint
  ipv4_subnet
  ipv6_address
  ipv6_endpoint
  ipv6_subnet
  local_group
  logger
  mailbox_element
  make_config_value_field
  message
  message_id
  message_lifetime
  metaprogramming
  mixin.requester
  mixin.sender
  mock_streaming_classes
  native_streaming_classes
  node_id
  optional
  or_else
  pipeline_streaming
  policy.categorized
  request_timeout
  result
  selective_streaming
  serialization
  settings
  simple_timeout
  span
  stateful_actor
  string_algorithms
  string_view
  sum_type
  thread_hook
  typed_behavior
  typed_response_promise
  typed_spawn
  unit
  uri
  variant
)

if(NOT CAF_NO_EXCEPTIONS)
  caf_add_test_suites(caf-core-test custom_exception_handler)
endif()
