# file      : libbutl/buildfile
# license   : MIT; see accompanying LICENSE file

lib{butl}: {hxx ixx txx cxx}{** -uuid-* +uuid-io         \
                                -win32-utility           \
                                -mingw-*                 \
                                -version                 \
                                -builtin-options}        \
           {hxx}{version} {hxx ixx cxx}{builtin-options}

tclass = $cxx.target.class
tsys   = $cxx.target.system

windows = ($tclass == 'windows')

# Whether to use our own implementation of C++14 threads on MinGW (note:
# requires Windows 7 or later).
#
# Note that for now we use built-in POSIX thread support during bootstrap
# (which, as a side effect, verifies we still use MinGW GCC configured with
# POSIX support, which we still need for TLS, exceptions, and thread-safe
# static locals).
#
mingw_stdthread = ($tsys == 'mingw32')

# Exclude these from compilation on targets where does not apply.
#
lib{butl}: {hxx ixx cxx}{win32-utility}: include = $windows
lib{butl}: hxx{mingw-*}: include = $mingw_stdthread

# Our C-files are always included into C++-files that wrap the corresponding
# API so treat them as files to exclude from the compilation.
#
lib{butl}: file{**.c **.h}

# Platform-specific UUID implementations.
#
lib{butl}: cxx{uuid-linux}:   include = ($tclass == 'linux')
lib{butl}: cxx{uuid-macos}:   include = ($tclass == 'macos')
lib{butl}: cxx{uuid-windows}: include = $windows
lib{butl}: cxx{uuid-freebsd}: include = ($tsys == 'freebsd' || $tsys == 'netbsd')
lib{butl}: cxx{uuid-openbsd}: include = ($tsys == 'openbsd')

# GCC prior to version 6 has flaky `#pragma GCC diagnostic` so we have to
# disable certain warnings outright.
#
if ($cxx.id == 'gcc' && $cxx.version.major < 6)
  cc.coptions += -Wno-unused-function

# Additional system libraries.
#
switch $tclass, $tsys
{
  case 'linux'
    cxx.libs += -ldl

  case 'macos'
    cxx.libs += -framework CoreFoundation

  case 'windows', 'mingw32'
    cxx.libs += -lrpcrt4 -limagehlp

  case 'windows'
    cxx.libs += rpcrt4.lib imagehlp.lib

  case 'bsd', 'freebsd' | 'netbsd'
    cxx.libs += -lexecinfo

  case 'bsd', 'openbsd'
  {
    # Built-in libexecinfo is only available since OpenBSD 7.0.
    #
    if (([uint64] $regex.replace($cxx.target.version, '(\d+)\..+', '\1')) >= 7)
      cxx.libs += -lexecinfo
  }
}

if! $windows
  cxx.libs += -lpthread

# Include the generated version header into the distribution (so that we don't
# pick up an installed one) and don't remove it when cleaning in src (so that
# clean results in a state identical to distributed).
#
hxx{version}: in{version} $src_root/manifest
hxx{version}:
{
  dist  = true
  clean = ($src_root != $out_root)
}

# Build options.
#
cxx.poptions =+ "-I$out_root" "-I$src_root"

if $mingw_stdthread
  cxx.poptions += -D_WIN32_WINNT=0x0601 -DLIBBUTL_MINGW_STDTHREAD

obja{*} bmia{*}: cxx.poptions += -DLIBBUTL_STATIC_BUILD
objs{*} bmis{*}: cxx.poptions += -DLIBBUTL_SHARED_BUILD

# Export options.
#
lib{butl}: cxx.export.poptions = "-I$out_root" "-I$src_root"

if $mingw_stdthread
  lib{butl}: cxx.export.poptions += -D_WIN32_WINNT=0x0601 -DLIBBUTL_MINGW_STDTHREAD

liba{butl}: cxx.export.poptions += -DLIBBUTL_STATIC
libs{butl}: cxx.export.poptions += -DLIBBUTL_SHARED

# 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{butl}: bin.lib.version = @"-$version.project_id"
else
  lib{butl}: bin.lib.version = @"-$version.major.$version.minor"

# Generated options parser.
#
if $cli.configured
{
  cli.cxx{builtin-options}: cli{builtin}

  cli.options += --std c++11 -I $src_root --include-with-brackets \
--include-prefix libbutl --guard-prefix LIBBUTL --cli-namespace butl::cli \
--generate-vector-scanner --generate-parse --keep-separator \
--generate-specifier --suppress-usage

  cli.cxx{*}:
  {
    # Include the generated cli files into the distribution and don't remove
    # them when cleaning in src (so that clean results in a state identical to
    # distributed). But don't install their headers since they are only used
    # internally in the builtins implementation.
    #
    dist  = true
    clean = ($src_root != $out_root)
    install = false

    # We keep the generated code in the repository so copy it back to src in
    # case of a forwarded configuration.
    #
    backlink = overwrite
  }
}
else
  # No install for the pre-generated case.
  #
  hxx{builtin-options}@./ ixx{builtin-options}@./: install = false

# Install into the libbutl/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
  install         = include/libbutl/
  install.subdirs = true
}
