# file      : libbuild2/buildfile
# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
# license   : MIT; see accompanying LICENSE file

# NOTE: remember to update bundled_modules in libbuild2/module.cxx if adding a
#       new module.
#
./: lib{build2} bash/ bin/ c/ cc/ cxx/ in/ version/

# A module should treat lib{build2} as an "implied interface dependency"
# meaning that it can link it as an implementation dependency and assume that
# whomever imports and links this module will also import and link lib{build2}
# explicitly. A module should also assume that lib{butl} will always be an
# interface dependency of lib{build2} and therefore need not be explicitly
# imported or linked.
#
import int_libs = libbutl%lib{butl}

lib{build2}: libul{build2}:                                            \
  {hxx ixx txx cxx}{* -utility-*installed -config -version -*.test...} \
  {hxx}{config version}

# Note that this won't work in libul{} since it's not installed.
#
lib{build2}: cxx{utility-installed}:   for_install = true
lib{build2}: cxx{utility-uninstalled}: for_install = false

# These are "core modules" that come bundled with libbuild2 (see also unit
# tests loop below). Note that the build system core can still function
# without them or with their alternative implementations.
#
# NOTE: remember to update import_modules() in libbuild2/modules.cxx if adding
#       a new such module.
#
for m: config dist install test
  libul{build2}: $m/{hxx ixx txx cxx}{** -**-options -**.test...}

libul{build2}: test/script/{hxx ixx cxx}{builtin-options}

libul{build2}: $int_libs

# Include the generated config and version headers into the distribution (so
# that we don't pick up installed ones) and don't remove them when cleaning in
# src (so that clean results in a state identical to distributed).
#
hxx{config}: in{config}
hxx{version}: in{version} $src_root/manifest

hxx{config version}:
{
  dist  = true
  clean = ($src_root != $out_root)
}

# Unit tests.
#
exe{*.test}:
{
  test = true
  install = false
}

for t:         cxx{ *.test...} \
        config/cxx{**.test...} \
          dist/cxx{**.test...} \
       install/cxx{**.test...} \
          test/cxx{**.test...}
{
  d = $directory($t)
  n = $name($t)...
  b = $path.base($name($t))

  ./: $d/exe{$n}: $t $d/{hxx ixx txx}{+$n} $d/testscript{+$n +$b+*.test...}
  $d/exe{$n}: libul{build2}: bin.whole = false
  $d/exe{$n}: cxx{utility-uninstalled}
}

# Build options.
#
# NOTE: this scope happens to be outer to the bundled modules which means they
#       will inherit any scope-wide options. So we should normally only set
#       them on targets.
#
obja{*}: cxx.poptions += -DLIBBUILD2_STATIC_BUILD
objs{*}: cxx.poptions += -DLIBBUILD2_SHARED_BUILD

# Pass our compiler target to be used as build2 host and our out_root to be
# used as the build system import path (unless cross-compiling and not
# forgetting to escape backslashes on Windows).
#
{obja objs}{context}: cxx.poptions += "-DBUILD2_HOST_TRIPLET=\"$cxx.target\""

# Note that we used to compare complete target triplets but that proved too
# strict. For example, we may be running on x86_64-apple-darwin17.7.0 while
# the compiler is targeting x86_64-apple-darwin17.3.0.
#
cross = ($cxx.target.cpu != $build.host.cpu || \
         $cxx.target.system != $build.host.system)

if! $cross
  {obja objs}{context}: cxx.poptions += \
    -DBUILD2_IMPORT_PATH=\"$regex.replace($out_root, '\\', '\\\\')\"

if ($cxx.target.class != 'windows')
{
  libul{build2}: cxx.libs += -lpthread

  if ($cxx.target.class != "bsd")
    libul{build2}: cxx.libs += -ldl
}

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

# While we don't call any pthread_*() functions in our API, this appears to be
# needed for some std::thread implementations (like libstdc++).
#
if ($cxx.target.class != 'windows')
  lib{build2}: cxx.export.libs += -lpthread

liba{build2}: cxx.export.poptions += -DLIBBUILD2_STATIC
libs{build2}: cxx.export.poptions += -DLIBBUILD2_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{build2}: bin.lib.version = @"-$version.project_id"
else
  lib{build2}: bin.lib.version = @"-$version.major.$version.minor"

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

    cli.options += --std c++11 -I $src_root --include-with-brackets \
--include-prefix libbuild2/test/script --guard-prefix LIBBUILD2_TEST_SCRIPT \
--cli-namespace build2::test::script::cli --generate-vector-scanner \
--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 testscript 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 libbuild2/ subdirectory of, say, /usr/include/
# recreating subdirectories.
#
{hxx ixx txx}{*}:
{
  install         = include/libbuild2/
  install.subdirs = true
}