Import('env')

# On x86 blake3 implements runtime CPU feature dispatch (via cpuid) to choose the
# best available SIMD implementation out of those compiled in. We build all of
# them unconditionally so the choice is made at runtime (based on the CPU that
# is executing rmlint) rather than at build time (based on the capabilities of
# the build host and/or the compilation flags which signify the baseline).
#
# On x86_64 we use the hand-written assembly sources which do not require any
# additional build flags. For i386 no assembly is provided, but the dispatch
# routine still looks for SIMD implementations, so we have to build the C sources
# and provide appropriate feature flags for each implementation.
#
# NB: We provide specific feature flags for each implementation (e.g. `-mavx2`
# for the AVX2 impl) *regardless* of the build target or the build CPU capabilities.
# This is safe and correct because the specific impl is chosen at runtime based
# on the executing CPU, and we do not "leak" the flags into other TUs.
#
# There is no runtime dispatch for aarch64 LE, compile-time BLAKE3_USE_NEON is used.

blake3 = [
    File('blake3/blake3.c'),
    File('blake3/blake3_portable.c'),
]

blake3_dispatch_flags = []

if env['IS_X86_64']:
    print('Compiling BLAKE3 using x86_64 SIMD assembly')
    flavor = 'windows_gnu' if env['IS_WINDOWS'] or env['IS_CYGWIN'] else 'unix'
    blake3 += [
        File('blake3/blake3_%s_x86-64_%s.S' % (isa, flavor))
        for isa in ('sse2', 'sse41', 'avx2', 'avx512')
    ]
elif env['IS_X86']:
    print('Compiling BLAKE3 using x86 SIMD C intrinsics')
    blake3_simd_flags = {
        'sse2':   ['-msse2'],
        'sse41':  ['-msse4.1'],
        'avx2':   ['-mavx2'],
        'avx512': ['-mavx512f', '-mavx512vl'],
    }
    blake3 += [
        env.Object(
            'blake3/blake3_%s.c' % isa,
            CCFLAGS=env['CCFLAGS'] + flags,
        )
        for isa, flags in blake3_simd_flags.items()
    ]
elif env['IS_AARCH64_LE']:
    # We could manually set BLAKE3_USE_NEON, but blake3_impl.h autodetects
    # this at compile time, let it do it.
    print('Compiling BLAKE3 using AArch64 NEON')
    blake3 += [File('blake3/blake3_neon.c')]
    # Keep blake3 vendored verbatim for now, ignore the warning.
    # see https://github.com/BLAKE3-team/BLAKE3/pull/344
    if env['IS_CLANG']:
        blake3_dispatch_flags += ['-Wno-unreachable-code-aggressive']
else:
    print('Not compiling BLAKE3 SIMD implementations (none for this target)')

blake3 += [env.Object('blake3/blake3_dispatch.c',
                      CCFLAGS=env['CCFLAGS'] + blake3_dispatch_flags)]

sources = (
    Glob('*.c') +
    Glob('xxhash/*.c') +
    Glob('blake2/*.c') +
    blake3 +
    Glob('sha3/*.c')
)

Return('sources')
