intf_libs = # Interface dependencies.
impl_libs = # Implementation dependencies.

# Public header.
#
pub = [dir_path] ../include/

include $pub

pub_hdrs = $($pub/ pub_hdrs)

lib{CMP_Core}: libul{CMP_Core}: $pub/{$pub_hdrs}

# Kernel sources matching CMP_Core in cmp_core/CMakeLists.txt. Optional
# GTC and Brotli-G kernels are omitted (upstream defaults GTC off, and
# Brotli-G is a separate SDK). FidelityFX headers are not part of the
# CPU library.
#
libul{CMP_Core}: cmp_core/shaders/{h cxx}{** -brlg_encode_kernel -ffx_a -ffx_cas -ffx_fsr1 -cmp_fsr1} \
                 cmp_core/source/{h cxx}{** -core_simd_sse -core_simd_avx -core_simd_avx512}

# cpu_extensions.cpp and cmp_math_common.cpp are listed on CMP_Core by
# upstream (not the rest of CMP_Math).
#
libul{CMP_Core}: cmp_math/{h cxx}{cpu_extensions cmp_math_common}

# SIMD TUs. Upstream always links CMP_Core_SSE/AVX/AVX512, whose
# symbols are referenced as function pointers from bc1_cmp.h. On
# non-x86 (and when a config switch is off) compile a stub instead so
# the portable CPU path still links.
#
libul{CMP_Core}: cmp_core/source/cxx{core_simd_sse}:    include = $config.libcmp_core.sse
libul{CMP_Core}: cmp_core/source/cxx{core_simd_avx}:    include = $config.libcmp_core.avx
libul{CMP_Core}: cmp_core/source/cxx{core_simd_avx512}: include = $config.libcmp_core.avx512

libul{CMP_Core}: cxx{core_simd_sse_stub}:    include = (!$config.libcmp_core.sse)
libul{CMP_Core}: cxx{core_simd_avx_stub}:    include = (!$config.libcmp_core.avx)
libul{CMP_Core}: cxx{core_simd_avx512_stub}: include = (!$config.libcmp_core.avx512)

libul{CMP_Core}: $impl_libs $intf_libs

libs{CMP_Core}: def{CMP_Core}: include = ($cxx.target.system == 'win32-msvc')
def{CMP_Core}: libul{CMP_Core}

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

# Private -I paths match upstream PUBLIC include dirs of CMP_Core
# (shaders, source, cmp_math). They are not exported.
#
cxx.poptions =+ "-I$out_pfx_inc" "-I$src_pfx_inc" \
                "-I$src_base/cmp_core/source" \
                "-I$src_base/cmp_core/shaders" \
                "-I$src_base/cmp_math"

# CMake: if (UNIX) target_compile_definitions(CMP_Core PRIVATE _LINUX ASPM_GPU)
# common_def.h then undefines ASPM_GPU on Apple/Linux so the CPU path is
# used.
#
if ($cxx.target.class != 'windows')
  cxx.poptions += -D_LINUX -DASPM_GPU

if ($cxx.target.system == 'mingw32')
{
  cxx.loptions += -Wl,--export-all-symbols

  # 'align' attribute directive ignored: ALIGN_16 (see below) has no
  # effect where the kernel headers apply it under MinGW. A missed
  # optimization hint, not a correctness issue.
  #
  cxx.coptions += -Wno-attributes
}

# Silence warnings in upstream GPU/CPU shared kernel headers. The comma
# operator returns in bcn_common_api.h are HLSL-style vector ctors.
#
if ($cxx.class != 'msvc')
  cxx.coptions += -Wno-unused-value

# The kernel headers dispatch multiple SIMD variants (portable/SSE/AVX/
# AVX512) from the same translation unit and declare helpers for levels
# the current TU does not use. GCC and Clang flag the unused ones, plus
# unrecognized GPU-side #pragma and brace-less subobject initializers
# that are upstream style, not bugs.
#
if ($cxx.class != 'msvc')
  cxx.coptions += -Wno-unused-function -Wno-unused-variable \
                  -Wno-unused-but-set-variable -Wno-unknown-pragmas \
                  -Wno-missing-braces

# Upstream's CGU_INT8/CGV_INT8 are plain `char`, whose signedness is
# implementation-defined. On the (uncommon) platforms where the ABI
# defaults it to unsigned, a couple of sentinel comparisons against
# negative literals (e.g. bestShape != -1 in bc6_encode_kernel.cpp) do
# not behave as upstream intends. Retyping char to signed char upstream-
# wide is not a local fix: it changes overload resolution and breaks
# pointer compatibility at existing plain-char call sites elsewhere in
# the same headers, so for now this is silenced rather than patched.
#
if ($cxx.class != 'msvc')
  cxx.coptions += -Wno-char-subscripts

# Match on cxx.id == 'clang' or 'clang-apple': Apple's Xcode toolchain
# reports a distinct id from upstream LLVM clang, and both need this.
#
if ($cxx.id == 'clang' || $cxx.id == 'clang-apple')
  cxx.coptions += -Wno-tautological-constant-out-of-range-compare

# bc1_cmp.h has a couple of `&&` inside `||` conditions where the
# (well-defined) operator precedence already matches the intent; GCC and
# Clang name the diagnostic differently.
#
if ($cxx.id == 'gcc')
  cxx.coptions += -Wno-parentheses
elif ($cxx.id == 'clang' || $cxx.id == 'clang-apple')
  cxx.coptions += -Wno-logical-op-parentheses

# GCC-only diagnostics checked against the actual code and found benign:
# bc1_cmp.h reads a float's bit pattern through a uint32_t* as an
# intentional fast "is this exactly zero" check, not accidental type
# punning; sortProjected_indexs in bc7_encode_kernel.cpp writes within
# the bounds of a fixed 16-element array that GCC misjudges at -O2/-O3;
# and -Wmaybe-uninitialized is GCC's own hedge on complex codec math it
# cannot fully trace (the one definite, unconditional uninitialized
# read, in cpu_extensions.cpp, is fixed at the source, not silenced).
#
if ($cxx.id == 'gcc')
  cxx.coptions += -Wno-strict-aliasing -Wno-stringop-overflow \
                  -Wno-maybe-uninitialized

# Per-TU architecture flags matching upstream CMP_Core_SSE / AVX /
# AVX512. These have local effect on the SIMD translation units only.
#
# Upstream builds the AVX512 TU with -march=knl, but GCC 15/16 dropped
# that value (Knights Landing support was removed). core_simd_avx512.cpp
# only uses baseline AVX512F intrinsics (_mm512_*), so -mavx512f is an
# equivalent, still-supported substitute.
#
# This must come after the warning-suppression cxx.coptions += above:
# target-specific += (unlike the plain += above it) freezes cxx.coptions
# for that target at whatever the directory scope holds at this point in
# the buildfile, so earlier placement silently dropped every suppression
# above for the SIMD TUs (visible as unknown-pragma and similar warnings
# leaking on x86 configs only, since non-x86 builds never compile these
# TUs).
#
if ($cxx.class == 'msvc')
{
  cmp_core/source/obj{core_simd_avx}:    cxx.coptions += /arch:AVX2
  cmp_core/source/obj{core_simd_avx512}: cxx.coptions += /arch:AVX512
}
else
{
  cmp_core/source/obj{core_simd_sse}:    cxx.coptions += -march=nehalem
  cmp_core/source/obj{core_simd_avx}:    cxx.coptions += -march=haswell
  cmp_core/source/obj{core_simd_avx512}: cxx.coptions += -mavx512f
}

# Export options.
#
lib{CMP_Core}:
{
  cxx.export.poptions = "-I$out_pfx_inc" "-I$src_pfx_inc"
  cxx.export.libs = $intf_libs

  # Non-build2 (pkg-config) consumers also get the unqualified include
  # path, matching upstream's own CMake public include path
  # (target_include_directories(CMP_Core PUBLIC shaders source ...)).
  # build2 consumers only ever see the qualified path above.
  #
  cxx.pkgconfig.include = include/ include/cmp_core/

  export.metadata = 1 libcmp_core
  libcmp_core.sse    = [bool] $config.libcmp_core.sse
  libcmp_core.avx    = [bool] $config.libcmp_core.avx
  libcmp_core.avx512 = [bool] $config.libcmp_core.avx512
}

if ($cxx.target.class != 'windows')
  lib{CMP_Core}: cxx.libs += -lm

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

# Don't install private headers.
#
cmp_core/h{**}: install = false
cmp_math/h{*}:  install = false
