# -*- mode: python -*-

Import("env")
Import("has_option")
Import("debugBuild")

# https://www.nongnu.org/libunwind/man/libunwind(3).html#section_1
# For local unwinding (introspection, which is all we want), include
# libunwind.h and link with '-lunwind'. We only need to build enough
# for that to work.
#
# Limited to linux_x86_64 right now.

env = env.Clone()

unwind_root = env.Dir(".").srcnode()
unwind_platform = unwind_root.Dir("platform/${TARGET_OS}_${TARGET_ARCH}")
unwind_src_dir = env.Dir("dist/src")

# Generated by a manual process:
#     - Run "scripts/host_config.sh |tee host_config.out".
#     - Gather .o dependencies of the libunwind.a target.
#     - Some .o are from prereq libraries, they have .lax paths.
#       Replace the `*.lax/$PREREQ/*.o` dependencies with the
#       corresponding .o from that $PREREQ library.
#     - Replace each .o with the source file (.c or .S) that generated it.
#     - Ensure the the ${CC} arguments are preserved by SCons.
unwind_sources = [
    'mi/backtrace.c',
    'mi/dyn-cancel.c',
    'mi/dyn-info-list.c',
    'mi/dyn-register.c',
    'mi/flush_cache.c',
    'mi/init.c',
    'mi/Ldestroy_addr_space.c',
    'mi/Ldyn-extract.c',
    'mi/Lfind_dynamic_proc_info.c',
    'mi/Lget_accessors.c',
    'mi/Lget_fpreg.c',
    'mi/Lget_proc_info_by_ip.c',
    'mi/Lget_proc_name.c',
    'mi/Lget_reg.c',
    'mi/Lput_dynamic_unwind_info.c',
    'mi/Lset_cache_size.c',
    'mi/Lset_caching_policy.c',
    'mi/Lset_fpreg.c',
    'mi/Lset_reg.c',
    'mi/mempool.c',
    'mi/strerror.c',
    'os-linux.c',
    #
    # x86_64
    'x86_64/is_fpreg.c',
    'x86_64/Lapply_reg_state.c',
    'x86_64/Lcreate_addr_space.c',
    'x86_64/Lget_proc_info.c',
    'x86_64/Lget_save_loc.c',
    'x86_64/Lglobal.c',
    'x86_64/Linit.c',
    'x86_64/Linit_local.c',
    'x86_64/Linit_remote.c',
    'x86_64/Los-linux.c',
    'x86_64/Lregs.c',
    'x86_64/Lreg_states_iterate.c',
    'x86_64/Lresume.c',
    'x86_64/Lstash_frame.c',
    'x86_64/Lstep.c',
    'x86_64/Ltrace.c',
    'x86_64/regname.c',
    'x86_64/getcontext.S',
    'x86_64/setcontext.S',
    #
    # orig in unwind-elf64
    'elf64.c',
    #
    # orig in unwind-dwarf-local
    'dwarf/Lexpr.c',
    'dwarf/Lfde.c',
    'dwarf/Lfind_proc_info-lsb.c',
    'dwarf/Lfind_unwind_table.c',
    'dwarf/Lparser.c',
    'dwarf/Lpe.c',
    #
    # orig in unwind-dwarf-common
    'dwarf/global.c',
]

env.Append(
    CCFLAGS=[
        '-fexceptions',
        '-Wno-unused-result',
    ])

if env.ToolchainIs('clang'):
    env.Append(CCFLAGS=['-Wno-header-guard'])

env.Append(
    CPPPATH=[
        unwind_platform.Dir("build/include"),
        unwind_root.Dir("dist/src"),
        unwind_root.Dir("dist/include"),
        unwind_root.Dir("dist/include/tdep-${TARGET_ARCH}"),
    ])

# propagates to consumers that Inject (depend on) unwind.
env.RegisterConsumerModifications(
    CPPPATH=[unwind_platform.Dir("install/include")],
    CPPDEFINES=['UNW_LOCAL_ONLY', 'MONGO_USE_LIBUNWIND'],
    LIBS=['lzma'])

env.Append(
    LIBS=['lzma'])

env.Append(
    CPPDEFINES=[
        'HAVE_CONFIG_H',
        '_GNU_SOURCE',
    ])

unwind_sources_files = [unwind_src_dir.File(f) for f in unwind_sources]
env.Library(
    target='unwind',
    source=unwind_sources_files)
