#  Boost.OpenMethod Library Test Jamfile
#
#  Copyright 2015-2019 Peter Dimov
#
#  Distributed under the Boost Software License, Version 1.0.
#  See accompanying file LICENSE_1_0.txt or copy at
#  http://www.boost.org/LICENSE_1_0.txt

import-search /boost/config/checks ;

import testing ;
import config : requires ;

use-project /boost/openmethod/config : ../config ;

project
  : requirements

    [ requires cxx17_auto_nontype_template_params cxx17_deduction_guides
      cxx17_fold_expressions cxx17_hdr_charconv cxx17_hdr_string_view
      cxx17_hdr_variant cxx17_if_constexpr cxx17_inline_variables
      cxx17_structured_bindings ]

    <library>/boost/openmethod//boost_openmethod
    <library>/boost/any//boost_any

    # Boost.TypeErasure, by include path rather than as a dependency.
    #
    # The interop needs its headers only. Its compiled part is one file,
    # dynamic_binding.cpp, which nothing here references and which links
    # Boost.Thread - which pulls in Boost.Container, Chrono, date_time and
    # Atomic. Two of those do not build under -Werror on the Windows CI
    # toolchains, and took this whole suite down with them.
    #
    # <library> builds all of that. <use> does not build it, but still is not
    # enough: naming the target makes b2 load Boost.Thread's Jamfile to
    # resolve type_erasure's own requirements, and that declares the
    # threadapi feature, which lands in the property set of every target in
    # the build - on Windows, enough to pull the dependency cluster in
    # anyway. Only not naming the target at all decouples us from it.
    #
    # The path is relative to this Jamfile, and b2 builds openmethod inside
    # boost-root, so the sibling library is where this says it is. The define
    # matches type_erasure's own usage requirement: it keeps MSVC from
    # auto-linking the library we are deliberately not building. Nothing here
    # reaches the header that would trigger that (register_binding.hpp), but
    # it costs nothing to say so.
    <include>../../type_erasure/include
    <define>BOOST_TYPE_ERASURE_NO_LIB=1

    # C++26 reflection (P2996). GCC provides it only behind a flag, and accepts
    # that flag only alongside a C++26 standard flag, so the probe compiles a
    # <meta> snippet with -freflection under whatever standard the build
    # request asks for, and answers yes only when both are in place. Probing
    # beats matching a toolset version in both directions: a GCC that predates
    # reflection rejects -freflection outright and would take the whole
    # directory down with it, and a later one that stops needing the flag is
    # not left out. The library needs nothing else: it detects reflection from
    # __cpp_impl_reflection, and falls back to explicit class registration.
    [ check-target-builds /boost/openmethod/config//has_reflection
        "C++26 reflection" : <cxxflags>-freflection ]

    <warnings>extra

    <toolset>clang:<warnings-as-errors>on
    <toolset>gcc:<warnings-as-errors>on
    <toolset>msvc:<warnings-as-errors>on

    # test_slot_allocator.cpp instantiates the compiler for two dozen
    # registries, more sections than a COFF object holds by default.
    <toolset>msvc:<cxxflags>/bigobj
    <target-os>windows,<toolset>gcc:<cxxflags>-Wa,-mbig-obj
    <target-os>cygwin,<toolset>gcc:<cxxflags>-Wa,-mbig-obj
  ;

alias unit_test_framework
    : # sources
        /boost/test//boost_unit_test_framework/<warnings-as-errors>off
    ;

local bmi2-sources =
    test_dispatch_minimal_cover_hash.cpp
    test_hash_policies.cpp
    ;

for local src in [ glob test_*.cpp : $(bmi2-sources) ]
{
  run $(src) unit_test_framework ;
}

# minimal_cover_hash dispatches with BMI2's pext, and because `hash` is inlined
# into every call the instruction has to be enabled for the whole translation
# unit - so the sources that name the policy are declared on their own, rather
# than through the glob above. Where the probe fails - ARM, or a compiler that
# will not take the flag - BOOST_OPENMETHOD_HAS_PEXT is 0 and the policy drops
# out of both files, so nothing here is conditional on the outcome except the
# flag itself.
for local src in $(bmi2-sources)
{
  run $(src) unit_test_framework
    : : :
      [ check-target-builds /boost/openmethod/config//has_bmi2
          "BMI2 pext" : <cxxflags>-mbmi2 ]
    ;
}

run mix_release_debug/main.cpp mix_release_debug/lib.cpp unit_test_framework ;


for local src in [ glob compile_fail_*.cpp ]
{
  compile-fail $(src) ;
}

build-project dynamic_loading ;
build-project implicit_shared_libraries ;

# quick (for CI)
alias quick
    : test_dispatch_lvalue_refs
      test_dispatch_rvalue_refs
      test_dispatch_pointer
      test_dispatch_shared_ptr_by_value
      test_dispatch_shared_ptr_by_ref
      test_dispatch_unique_ptr
      test_dispatch_multi
      test_dispatch_next_fn
      test_dispatch_across_namespaces
      test_dispatch_comma_in_return_type
    ;
explicit quick ;
