# Generate the config.h file
# ===========================
# This creates config/gridcoin-config.h in the build directory
# (e.g., build/config/gridcoin-config.h) with all the
# correct HAVE_... definitions from the checks above.
configure_file(
    config/gridcoin-config.h.cmake.in
    config/gridcoin-config.h
)
configure_file(
    obj/build.h.in
    obj/build.h
)

add_compile_definitions(
    BOOST_SPIRIT_THREADSAFE
    __STDC_FORMAT_MACROS
)

# Multiprocess (IPC) build, RFC #2937: src/ipc is add_subdirectory'd later in this
# file (after gridcoin_util is defined, since the generated proxy layer links it
# for the core interface headers). See the ENABLE_MULTIPROCESS block near the end.

if(WIN32)
    # _WIN32_WINNT is already defined by the toolchain/CMake.
    # We remove it here to avoid "redefined" warnings.
    add_compile_definitions(_MT _WINDOWS)
    add_compile_definitions(WIN32 BOOST_THREAD_USE_LIB UNICODE)
elseif(UNIX AND NOT APPLE)
    add_compile_definitions(_FILE_OFFSET_BITS=64)
endif()

# These two files MUST be removed during a cmake build to ensure that an unclean autotools
# in-source build does not pollute the cmake build process.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config/gridcoin-config.h")
    message(STATUS "Detected stale Autotools configuration file. Removing: ${CMAKE_CURRENT_SOURCE_DIR}/config/gridcoin-config.h")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/config/gridcoin-config.h")
endif()

if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/obj/build.h")
    message(STATUS "Detected stale Autotools configuration file. Removing: ${CMAKE_CURRENT_SOURCE_DIR}/obj/build.h")
    file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/obj/build.h")
endif()

# Dependencies
# ============

if(SYSTEM_BDB)
    set(LIBBDB_CXX BerkeleyDB::CXX)
else()
    add_subdirectory(bdb53)
    set(LIBBDB_CXX libdb_cxx)
endif()

if(SYSTEM_LEVELDB)
    set(LIBLEVELDB leveldb::leveldb)
else()
    set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)

    set(LEVELDB_BUILD_TESTS OFF)
    set(LEVELDB_BUILD_BENCHMARKS OFF)
    set(LEVELDB_INSTALL OFF)

    set(HAVE_CRC32C OFF)
    set(HAVE_SNAPPY OFF)
    set(HAVE_TCMALLOC OFF)
    set(HAVE_CLANG_THREAD_SAFETY OFF)

    set(BUILD_SHARED_LIBS_ORIG ${BUILD_SHARED_LIBS})
    set(BUILD_SHARED_LIBS OFF)

    add_subdirectory(leveldb)
    set(LIBLEVELDB leveldb)

    set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_ORIG})
endif()

if(SYSTEM_SECP256K1)
    set(LIBSECP256K1 PkgConfig::SECP256K1)
else()
    set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)

    set(SECP256K1_DISABLE_SHARED ON CACHE BOOL "" FORCE)
    set(SECP256K1_ENABLE_MODULE_ECDH OFF)
    set(SECP256K1_ENABLE_MODULE_RECOVERY ON)
    set(SECP256K1_ENABLE_MODULE_EXTRAKEYS OFF)
    set(SECP256K1_ENABLE_MODULE_SCHNORRSIG OFF)
    set(SECP256K1_ENABLE_MODULE_MUSIG OFF)
    set(SECP256K1_VALGRIND OFF)

    set(SECP256K1_BUILD_BENCHMARK OFF)
    set(SECP256K1_BUILD_TESTS OFF)
    set(SECP256K1_BUILD_EXHAUSTIVE_TESTS OFF)
    set(SECP256K1_BUILD_CTIME_TESTS OFF)

    if(USE_ASM)
        set(SECP256K1_ASM "AUTO")
    else()
        set(SECP256K1_ASM "OFF")
    endif()

    add_subdirectory(secp256k1 EXCLUDE_FROM_ALL)
    set(LIBSECP256K1 secp256k1)
endif()

if(SYSTEM_UNIVALUE)
    set(LIBUNIVALUE PkgConfig::UNIVALUE)
else()
    add_subdirectory(univalue)
    set(LIBUNIVALUE univalue)
endif()


# libgridcoin_crypto
# ==================

add_subdirectory(crypto)


# libgridcoin_util
# ================

add_library(gridcoin_util STATIC
    addrdb.cpp
    addrman.cpp
    alert.cpp
    arith_uint256.cpp
    banman.cpp
    base58.cpp
    chain.cpp
    chainparams.cpp
    chainparamsbase.cpp
    checkpoints.cpp
    clientversion.cpp
    consensus/merkle.cpp
    consensus/tx_verify.cpp
    crypter.cpp
    dbwrapper.cpp
    fs.cpp
    htlc.cpp
    gridcoin/backup.cpp
    gridcoin/beacon.cpp
    gridcoin/block_claims.cpp
    gridcoin/boinc.cpp
    gridcoin/crypto/rsaverify.cpp
    gridcoin/claim.cpp
    gridcoin/consensus/block_rewards.cpp
    gridcoin/contract/contract.cpp
    gridcoin/contract/message.cpp
    gridcoin/contract/registry.cpp
    gridcoin/cpid.cpp
    gridcoin/gridcoin.cpp
    gridcoin/interfaces.cpp
    gridcoin/mnemonics.cpp
    gridcoin/mrc.cpp
    gridcoin/pool.cpp
    gridcoin/project.cpp
    gridcoin/protocol.cpp
    gridcoin/quorum.cpp
    gridcoin/researcher.cpp
    gridcoin/scraper/http.cpp
    gridcoin/scraper/scraper.cpp
    gridcoin/scraper/scraper_net.cpp
    gridcoin/scraper/scraper_registry.cpp
    gridcoin/sidestake.cpp
    gridcoin/staking/chain_trust.cpp
    gridcoin/staking/difficulty.cpp
    gridcoin/staking/exceptions.cpp
    gridcoin/staking/kernel.cpp
    gridcoin/staking/reward.cpp
    gridcoin/staking/status.cpp
    gridcoin/superblock.cpp
    gridcoin/support/block_finder.cpp
    gridcoin/tally.cpp
    gridcoin/tx_message.cpp
    gridcoin/upgrade.cpp
    gridcoin/voting/builders.cpp
    gridcoin/voting/claims.cpp
    gridcoin/voting/poll.cpp
    gridcoin/voting/poll_result_cache.cpp
    gridcoin/voting/registry.cpp
    gridcoin/voting/result.cpp
    gridcoin/voting/vote.cpp
    hash.cpp
    init.cpp
    interfaces/handler.cpp
    interfaces/init.cpp
    key.cpp
    key_io.cpp
    keystore.cpp
    logging.cpp
    merkleblock.cpp
    miner.cpp
    net.cpp
    net_processing.cpp
    netaddress.cpp
    netbase.cpp
    node/blockstorage.cpp
    node/chainman.cpp
    node/coherence.cpp
    node/interfaces.cpp
    node/mempool_persist.cpp
    node/orphan_blocks.cpp
    node/psgt_pool.cpp
    node/shutdown.cpp
    node/ui_interface.cpp
    noui.cpp
    pbkdf2.cpp
    policy/policy.cpp
    primitives/transaction.cpp
    primitives/block.cpp
    psgt.cpp
    protocol.cpp
    pubkey.cpp
    random.cpp
    randomenv.cpp
    rpc/blockchain.cpp
    rpc/htlc.cpp
    rpc/client.cpp
    rpc/dataacq.cpp
    rpc/mempool.cpp
    rpc/mining.cpp
    rpc/misc.cpp
    rpc/net.cpp
    rpc/protocol.cpp
    rpc/psgt.cpp
    rpc/rawtransaction.cpp
    rpc/server.cpp
    rpc/util.cpp
    rpc/voting.cpp
    scheduler.cpp
    script.cpp
    script/interpreter.cpp
    script/script.cpp
    script/sign.cpp
    script/standard.cpp
    scrypt.cpp
    support/cleanse.cpp
    support/lockedpool.cpp
    sync.cpp
    txmempool.cpp
    uint256.cpp
    util.cpp
    util/bip32.cpp
    util/proc_hardening.cpp
    util/settings.cpp
    util/sock.cpp
    util/strencodings.cpp
    util/string.cpp
    util/syserror.cpp
    util/dir_permissions.cpp
    util/system.cpp
    util/threadinterrupt.cpp
    util/threadnames.cpp
    util/time.cpp
    util/tokenpipe.cpp
    validation.cpp
    validationinterface.cpp
    wallet/coinviews.cpp
    wallet/cursor.cpp
    wallet/db.cpp
    wallet/diagnose.cpp
    wallet/interfaces.cpp
    wallet/rpcdump.cpp
    wallet/rpcwallet.cpp
    wallet/synthetic_coin_source.cpp
    wallet/transactionrecord.cpp
    wallet/txdetail.cpp
    wallet/txfilter.cpp
    wallet/txorder.cpp
    wallet/wallet.cpp
    wallet/wallet_coin_source.cpp
    wallet/wallet_tx_source.cpp
    wallet/walletcoinstore.cpp
    wallet/walletdb.cpp
    wallet/wallettxstore.cpp
    wallet/walletutil.cpp
)

if(USE_ASM_SCRYPT)
    target_sources(gridcoin_util PRIVATE scrypt-x86.S scrypt-x86_64.S)
endif()

target_include_directories(gridcoin_util PUBLIC
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_BINARY_DIR}/src
)

target_link_libraries(gridcoin_util PUBLIC
    ${LIBBDB_CXX} ${LIBLEVELDB} ${LIBSECP256K1} ${LIBUNIVALUE}
    Boost::boost Boost::filesystem Boost::iostreams Boost::thread Boost::date_time Boost::serialization
    CURL::libcurl
    # OpenSSL::SSL is linked for libcurl, NOT for the RPC server.
    #
    # -rpcssl is gone and no Gridcoin code calls into libssl any more, which
    # made this look removable. It is not: the scraper fetches project
    # statistics over HTTPS through libcurl, whose OpenSSL backend needs these
    # symbols. A dynamic build hides that -- libcurl.so pulls libssl.so in
    # transitively -- so removing it builds and links cleanly on the native
    # target and fails only in the static depends build, with 54 undefined
    # SSL_* references out of libcurl.a.
    OpenSSL::Crypto OpenSSL::SSL
    Threads::Threads
    ZLIB::ZLIB
)

if(UNIX)
    target_link_libraries(gridcoin_util PUBLIC -lm ${ATOMICS_LIBRARIES} ${RT_LIBRARIES})
endif()

target_link_libraries(gridcoin_util PUBLIC ${LIBGRIDCOIN_CRYPTO})

# advapi32: util/dir_permissions.cpp applies the owner-only NTFS DACL that protects
# a freshly created data directory (SetNamedSecurityInfoW / SetEntriesInAclW /
# GetNamedSecurityInfoW). This lives in gridcoin_util rather than gridcoin_ipc
# because the monolithic build creates data directories too (the Qt chooser) and
# gridcoin_ipc is only built when ENABLE_MULTIPROCESS=ON.
if(WIN32)
    target_link_libraries(gridcoin_util PUBLIC advapi32)
endif()

# Multiprocess (IPC) build, RFC #2937. src/ipc owns the libmultiprocess runtime +
# mpgen (built from the in-tree subtree in the default vendored mode) and the
# generated Cap'n Proto proxy layer (gridcoin_ipc). Added here, after gridcoin_util
# is defined, because the generated proxy code includes the interfaces:: headers,
# which transitively pull core headers (univalue, etc.); gridcoin_ipc links
# gridcoin_util for that include environment. The proxy targets are
# EXCLUDE_FROM_ALL; no Gridcoin binary links them yet (transport + client wiring
# are later Phase 2 steps).
if(ENABLE_MULTIPROCESS)
    add_subdirectory(ipc)
endif()

if(WIN32)
    target_link_libraries(gridcoin_util PUBLIC
        wsock32
        ws2_32
        wldap32
        crypt32
        bcrypt
        shlwapi
        iphlpapi
        )
endif()

target_compile_definitions(gridcoin_util PUBLIC
    HAVE_CONFIG_H
    HAVE_BUILD_INFO
    CURL_STATICLIB
)

if(ENABLE_UPNP)
    if(DEFAULT_UPNP)
        target_compile_definitions(gridcoin_util PRIVATE USE_UPNP=1)
    else()
        target_compile_definitions(gridcoin_util PRIVATE USE_UPNP=0)
    endif()

    if(WIN32)
        target_compile_definitions(gridcoin_util PRIVATE MINIUPNP_STATICLIB)
    endif()

    target_link_libraries(gridcoin_util PUBLIC ${LIBMINIUPNPC})
endif()

if(ENABLE_DEBUG_LOCKORDER)
    target_compile_definitions(gridcoin_util PUBLIC DEBUG_LOCKORDER)
endif()

# Daemon
# ======

if(ENABLE_DAEMON)
    add_executable(gridcoinresearchd gridcoinresearchd.cpp)
    target_include_directories(gridcoinresearchd PRIVATE ${CMAKE_BINARY_DIR})
    target_compile_definitions(gridcoinresearchd PRIVATE CURL_STATICLIB) # <--- ADDED

    # Multiprocess (RFC #2937): the daemon links the IPC layer so -multiprocess can
    # serve the GUI over the socket. gridcoin_ipc is EXCLUDE_FROM_ALL, so listing it
    # here is what pulls it into the build for this configuration.
    if(ENABLE_MULTIPROCESS)
        target_link_libraries(gridcoinresearchd PRIVATE gridcoin_ipc)
    endif()

    # Link gridcoinresearchd to gridcoin_util AND all of gridcoin_util's
    # dependencies, because it is a static library.
    target_link_libraries(gridcoinresearchd PUBLIC
        ${RUNTIME_LIBS}
        gridcoin_util

        # Dependencies of gridcoin_util
        ${LIBBDB_CXX} ${LIBLEVELDB} ${LIBSECP256K1} ${LIBUNIVALUE}
        Boost::boost Boost::filesystem Boost::iostreams Boost::thread Boost::date_time Boost::serialization
        CURL::libcurl
        OpenSSL::Crypto OpenSSL::SSL
        Threads::Threads
        ZLIB::ZLIB
    )

    if(WIN32)
        # Link the windows-specific libs
        target_link_libraries(gridcoinresearchd PUBLIC wsock32 ws2_32)

        target_sources(gridcoinresearchd PRIVATE gridcoinresearchd-res.rc)
        set_source_files_properties(gridcoinresearchd-res.rc PROPERTIES
            COMPILE_FLAGS "-I${CMAKE_BINARY_DIR}"
            COMPILE_DEFINITIONS WINDRES_PREPROC
        )
    endif()

    if(UNIX)
        # Link the unix-specific libs
        target_link_libraries(gridcoinresearchd PUBLIC
            -lm ${ATOMICS_LIBRARIES} ${RT_LIBRARIES}
        )
    endif()

    set_target_properties(gridcoinresearchd PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
    )

    # Installation
    if(UNIX AND NOT APPLE)
        include(GNUInstallDirs)
        install(TARGETS gridcoinresearchd COMPONENT daemon
            DESTINATION "${CMAKE_INSTALL_BINDIR}"
        )
        install(FILES "${CMAKE_SOURCE_DIR}/doc/gridcoinresearchd.1" COMPONENT daemon
            DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
        )
        install(FILES "${CMAKE_SOURCE_DIR}/contrib/init/gridcoinresearchd.service" COMPONENT daemon
            DESTINATION "lib/systemd/system"
        )
        install(FILES "${CMAKE_SOURCE_DIR}/contrib/init/gridcoinresearchd-autounlock.service" COMPONENT daemon
            DESTINATION "lib/systemd/system"
        )
        # The stake-only autounlock helper the unit above runs. install(PROGRAMS ...)
        # sets the executable bit; share/gridcoin is portable (share == share on
        # every distro), matching the unit's ExecStart path.
        install(PROGRAMS "${CMAKE_SOURCE_DIR}/contrib/wallettools/gridcoin_autounlock.py" COMPONENT daemon
            DESTINATION "${CMAKE_INSTALL_DATADIR}/gridcoin"
        )
        install(FILES "${CMAKE_SOURCE_DIR}/contrib/completions/bash/gridcoinresearchd.bash" COMPONENT daemon
            DESTINATION "${CMAKE_INSTALL_DATADIR}/bash-completion/completions"
            RENAME "gridcoinresearchd"
        )
    else()
        install(TARGETS gridcoinresearchd COMPONENT daemon
            RUNTIME DESTINATION bin
            BUNDLE  DESTINATION "."
        )
        if(WIN32)
            # Bundle the PowerShell helpers that run the multiprocess core as a background
            # scheduled task and provide opt-in stake-only autounlock. They install into the
            # package's windows\ folder (NSIS.template.in Files them into $INSTDIR\windows);
            # from there the scripts resolve the daemon at ..\daemon\gridcoinresearchd.exe and
            # the GUI at ..\gridcoinresearch.exe, matching the installed layout.
            install(FILES
                "${CMAKE_SOURCE_DIR}/contrib/windows/Install-GridcoinCoreTask.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Uninstall-GridcoinCoreTask.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Update-GridcoinCore.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Start-GridcoinGui.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Set-GridcoinAutounlock.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Invoke-GridcoinAutounlock.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/Set-GridcoinShutdownFlush.ps1"
                "${CMAKE_SOURCE_DIR}/contrib/windows/README.md"
                COMPONENT daemon
                DESTINATION windows
            )
        endif()
    endif()
endif()

# Qt GUI
# ======

if(ENABLE_GUI)
    add_subdirectory(qt)
endif()


# Tests
# =====

if(ENABLE_TESTS)
    add_subdirectory(test)
endif()
