import intf_libs  = libboost-assert%lib{boost_assert}
import intf_libs += libboost-atomic%lib{boost_atomic}
import intf_libs += libboost-config%lib{boost_config}
import intf_libs += libboost-core%lib{boost_core}
import intf_libs += libboost-date-time%lib{boost_date_time}
import intf_libs += libboost-exception%lib{boost_exception}
import intf_libs += libboost-filesystem%lib{boost_filesystem}
import intf_libs += libboost-function-types%lib{boost_function_types}
import intf_libs += libboost-fusion%lib{boost_fusion}
import intf_libs += libboost-intrusive%lib{boost_intrusive}
import intf_libs += libboost-iterator%lib{boost_iterator}
import intf_libs += libboost-move%lib{boost_move}
import intf_libs += libboost-mpl%lib{boost_mpl}
import intf_libs += libboost-optional%lib{boost_optional}
import intf_libs += libboost-parameter%lib{boost_parameter}
import intf_libs += libboost-phoenix%lib{boost_phoenix}
import intf_libs += libboost-preprocessor%lib{boost_preprocessor}
import intf_libs += libboost-property-tree%lib{boost_property_tree}
import intf_libs += libboost-proto%lib{boost_proto}
import intf_libs += libboost-range%lib{boost_range}
import intf_libs += libboost-regex%lib{boost_regex}
import intf_libs += libboost-smart-ptr%lib{boost_smart_ptr}
import intf_libs += libboost-spirit%lib{boost_spirit}
import intf_libs += libboost-system%lib{boost_system}
import intf_libs += libboost-thread%lib{boost_thread}
import intf_libs += libboost-throw-exception%lib{boost_throw_exception}
import intf_libs += libboost-type-index%lib{boost_type_index}
import intf_libs += libboost-type-traits%lib{boost_type_traits}
import intf_libs += libboost-utility%lib{boost_utility}
import intf_libs += libboost-winapi%lib{boost_winapi}
import intf_libs += libboost-xpressive%lib{boost_xpressive}
import impl_libs  = libboost-align%lib{boost_align}
import impl_libs += libboost-asio%lib{boost_asio}
import impl_libs += libboost-interprocess%lib{boost_interprocess}
import impl_libs += libboost-io%lib{boost_io}
import impl_libs += libboost-predef%lib{boost_predef}

intf_libs = $cxx.deduplicate_export_libs($intf_libs)

# Public headers.
#
pub = [dir_path] ../include/boost/

include $pub

pub_hdrs = $($pub/ pub_hdrs)

# BEGIN MANUAL CUSTOMIZATION
#

windows = ($cxx.target.class == 'windows')

# Boost.Log's SSSE3-optimized dump implementation (dump_ssse3.cpp) and the
# BOOST_LOG_USE_SSSE3 macro are x86-only. The generic dump.cpp is used
# elsewhere. Gate them on the target CPU so non-x86 targets (e.g. aarch64) do
# not try to compile x86 intrinsics or pass -msse* options.
#
x86 = ($cxx.target.cpu == 'x86_64' || $cxx.target.cpu == 'i686')

libs = boost_log boost_log_setup

# Splitting the library headers feels a bit hairy. Let's keep it simple and
# consider both libraries sharing the same full set of public headers under
# the boost/log/ subdirectory.
#
./: lib{$libs}: $pub/{$pub_hdrs}

# Private headers and sources as well as dependencies.
#
# Disable AVX2 support because it seems to be fairly new: the first supporting
# Intel CPU was Haswell in 2013 and the first AMD one was Excavator in 2015.
#
lib{boost_log}: {hxx ixx txx cxx}{** -posix/**    \
                                     -windows/**  \
                                     -setup/**    \
                                     -dump_avx2   \
                                     -dump_ssse3} \
                file{windows/simple_event_log.mc}

# The SSSE3 dump implementation is x86-only (see the x86 variable above).
#
lib{boost_log}: cxx{dump_ssse3}: include = $x86

# Disable Event Log support (Windows only) for now because, although `mc.exe`,
# which is required to generate `event_log_backend.h` from
# `event_log_backend.mc`, is part of the platform SDK, it is not available
# under MinGW. (Note that, if Event Log support is ever enabled, we will need
# to add `psapi.lib` to cxx.libs below.)
#
lib{boost_log}: windows/{hxx ixx txx}{**}:          include = $windows
lib{boost_log}: windows/cxx{** -event_log_backend}: include = $windows
lib{boost_log}: posix/{hxx ixx txx cxx}{**}:        include = (! $windows)

lib{boost_log_setup}: setup/{hxx ixx txx cxx}{**} lib{boost_log}

# While these libraries have potentially different dependency sets we are
# unable to easily deduce them, since `boostdep` is not of much help here. We
# also don't want to maintain these sets manually. Thus, let's assume that
# both libraries require the full set of dependencies.
#
# Note also that because log is an interface dependency of log_setup, we
# omit $intf_libs from its dependency list (in a sense, this is the manual
# version of $cxx.deduplicate_export_libs() above).
#
lib{boost_log}: $intf_libs
lib{$libs}:     $impl_libs

#
# END MANUAL CUSTOMIZATION

# Build options.
#
out_pfx_inc = [dir_path] $out_root/include/
src_pfx_inc = [dir_path] $src_root/include/
out_pfx_src = [dir_path] $out_root/src/
src_pfx_src = [dir_path] $src_root/src/

# BEGIN MANUAL CUSTOMIZATION
#

cxx.poptions =+ "-I$out_pfx_src" "-I$src_pfx_src" \
                "-I$out_pfx_inc" "-I$src_pfx_inc" \
                -D__STDC_CONSTANT_MACROS -DBOOST_SPIRIT_USE_PHOENIX_V3=1

if $windows
{
  # See above regarding the disabling of Event Log support.
  #
  cxx.poptions += -DBOOST_LOG_WITHOUT_EVENT_LOG    \
                  -DWIN32_LEAN_AND_MEAN -DNOMINMAX \
                  -DSECURITY_WIN32 -DBOOST_USE_WINDOWS_H
}
else
{
  cxx.poptions += -DBOOST_LOG_HAS_PTHREAD_MUTEX_ROBUST \
                  -DBOOST_LOG_USE_NATIVE_SYSLOG

  if ($cxx.target.class == 'linux')
    cxx.poptions += -D_XOPEN_SOURCE=600
}

# The names of the object files comprising lib{boost_log} and
# lib{boost_log_setup}, respectively.
#
objn       = $regex.apply({**.cpp -setup/**.cpp}, '.cpp$', '')
setup_objn = $regex.apply({        setup/**.cpp}, '.cpp$', '')

{hbmi  obj }{$objn}: cxx.poptions += -DBOOST_LOG_BUILDING_THE_LIB=1
{hbmis objs}{$objn}: cxx.poptions += -DBOOST_LOG_DLL

# Only advertise the SSSE3 dump implementation on x86 (where dump_ssse3.cpp is
# compiled; see above).
#
if $x86
  {hbmi obj}{$objn}: cxx.poptions += -DBOOST_LOG_USE_SSSE3

# Note that lib{boost_log_setup}'s object files will get
# -DBOOST_LOG_DYN_LINK=1 because it is exported from lib{boost_log}. The
# upstream build defines this macro explicitly but this is demonstrably
# redundant.
#
{hbmi  obj }{$setup_objn}: cxx.poptions += -DBOOST_LOG_SETUP_BUILDING_THE_LIB=1
{hbmis objs}{$setup_objn}: cxx.poptions += -DBOOST_LOG_SETUP_DLL

# SSE compiler options.
#
# Do not pass any SSE compiler options to MSVC because on x86 it's enabled by
# default (`/arch:SSE2`) and on x86_64 it is always enabled. Note that, to get
# SSE3 and SSSE3, we'd need to pass /arch:AVX which we've decided not to do
# (see above).
#
if ($cxx.class == 'gcc' && $x86)
  {hbmi obj}{dump_ssse3}: cxx.coptions += -msse -msse2 -msse3 -mssse3

switch $cxx.target.class, $cxx.target.system
{
  case 'windows', 'mingw32'
    lib{boost_log}: cxx.libs += -lsecur32 -lws2_32 -lmswsock -ladvapi32
  case 'windows'
    lib{boost_log}: cxx.libs += secur32.lib ws2_32.lib mswsock.lib advapi32.lib
  case 'linux'
  case 'bsd', 'freebsd'
    lib{boost_log}: cxx.libs += -lrt
}

# Export options.
#
lib{boost_log}:
{
  cxx.export.poptions = "-I$out_pfx_inc" "-I$src_pfx_inc" \
                         -DBOOST_LOG_NO_LIB
  cxx.export.libs     = $intf_libs
}
libs{boost_log}: cxx.export.poptions += -DBOOST_LOG_DYN_LINK=1


lib{boost_log_setup}:
{
  # Note that `generate` will define BOOST_LOG_NO_LIB in lib{boost_log}'s
  # export options above.
  #
  cxx.export.poptions = "-I$out_pfx_inc" "-I$src_pfx_inc" \
                        -DBOOST_LOG_SETUP_NO_LIB
  cxx.export.libs     = lib{boost_log}
}
libs{boost_log_setup}: cxx.export.poptions += -DBOOST_LOG_SETUP_DYN_LINK=1

# For pre-releases use the complete version to make sure they cannot be used
# in place of another pre-release or the final version. See the version module
# for details on the version.* variable values.
#
if $version.pre_release
  lib{$libs}: bin.lib.version = "-$version.project_id"
else
  lib{$libs}: bin.lib.version = "-$version.major.$version.minor"

#
# END MANUAL CUSTOMIZATION

# Don't install private headers.
#
{hxx ixx txx}{*}: install = false
