# Copyright (c) 2023-present The Glcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://opensource.org/license/mit/.

include(AddWindowsResources)

configure_file(${PROJECT_SOURCE_DIR}/cmake/glcoin-build-config.h.in glcoin-build-config.h USE_SOURCE_PERMISSIONS @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

#=============================
# Subprojects
#=============================
# Subprojects include subdirectories that do or could have tests
# and/or benchmark binaries, such as all subtrees and univalue.
# These need to be included before CMAKE_*_OUTPUT_DIRECTORY variables
# are set, so output locations of subproject tests and libraries are
# not overridden.
include(../cmake/crc32c.cmake)
include(../cmake/leveldb.cmake)
include(../cmake/minisketch.cmake)
add_subdirectory(univalue)
if (ENABLE_IPC AND NOT WITH_EXTERNAL_LIBMULTIPROCESS)
  include(../cmake/libmultiprocess.cmake)
  add_libmultiprocess(ipc/libmultiprocess)
endif()
include(../cmake/secp256k1.cmake)
add_secp256k1(secp256k1)

# Set top-level target output locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
endif()
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
endif()

add_custom_target(generate_build_info
  BYPRODUCTS ${PROJECT_BINARY_DIR}/src/glcoin-build-info.h
  COMMAND ${CMAKE_COMMAND} -DBUILD_INFO_HEADER_PATH=${PROJECT_BINARY_DIR}/src/glcoin-build-info.h -DSOURCE_DIR=${PROJECT_SOURCE_DIR} -P ${PROJECT_SOURCE_DIR}/cmake/script/GenerateBuildInfo.cmake
  COMMENT "Generating glcoin-build-info.h"
  VERBATIM
)
add_library(glcoin_clientversion STATIC
  clientversion.cpp
)
target_link_libraries(glcoin_clientversion
  PRIVATE
    core_interface
)
add_dependencies(glcoin_clientversion generate_build_info)

add_subdirectory(crypto)
add_subdirectory(util)
if(ENABLE_IPC)
  add_subdirectory(ipc)
else()
  add_library(glcoin_ipc STATIC EXCLUDE_FROM_ALL ipc/stub.cpp)
endif()

add_library(glcoin_consensus STATIC EXCLUDE_FROM_ALL
  arith_uint256.cpp
  consensus/merkle.cpp
  consensus/tx_check.cpp
  hash.cpp
  primitives/block.cpp
  primitives/transaction.cpp
  pubkey.cpp
  script/interpreter.cpp
  script/script.cpp
  script/script_error.cpp
  uint256.cpp
)
target_link_libraries(glcoin_consensus
  PRIVATE
    core_interface
    glcoin_crypto
    secp256k1
)

if(WITH_ZMQ)
  add_subdirectory(zmq)
endif()

# Home for common functionality shared by different executables and libraries.
# Similar to `glcoin_util` library, but higher-level.
add_library(glcoin_common STATIC EXCLUDE_FROM_ALL
  addresstype.cpp
  base58.cpp
  bech32.cpp
  chain.cpp
  chainparams.cpp
  chainparamsbase.cpp
  coins.cpp
  common/args.cpp
  common/bloom.cpp
  common/config.cpp
  common/init.cpp
  common/interfaces.cpp
  common/license_info.cpp
  common/messages.cpp
  common/netif.cpp
  common/pcp.cpp
  common/run_command.cpp
  common/settings.cpp
  common/signmessage.cpp
  common/system.cpp
  common/url.cpp
  compressor.cpp
  core_io.cpp
  deploymentinfo.cpp
  external_signer.cpp
  init/common.cpp
  kernel/chainparams.cpp
  key.cpp
  key_io.cpp
  merkleblock.cpp
  musig.cpp
  net_permissions.cpp
  net_types.cpp
  netaddress.cpp
  netbase.cpp
  outputtype.cpp
  policy/feerate.cpp
  policy/policy.cpp
  pow.cpp
  protocol.cpp
  psbt.cpp
  rpc/rawtransaction_util.cpp
  rpc/request.cpp
  rpc/util.cpp
  scheduler.cpp
  script/descriptor.cpp
  script/miniscript.cpp
  script/parsing.cpp
  script/sign.cpp
  script/signingprovider.cpp
  script/solver.cpp
  util/anchorowner.cpp
  util/cid.cpp
  util/metrics.cpp
  util/ocsf_log.cpp
  util/otp.cpp
  crypto/glce.cpp
)
target_link_libraries(glcoin_common
  PRIVATE
    core_interface
    glcoin_consensus
    glcoin_util
    univalue
    secp256k1
    $<TARGET_NAME_IF_EXISTS:USDT::headers>
    $<$<PLATFORM_ID:Windows>:ws2_32>
)

include(InstallBinaryComponent)

if(ENABLE_WALLET)
  add_subdirectory(wallet)

  if(BUILD_WALLET_TOOL)
    add_executable(glcoin-wallet
      glcoin-wallet.cpp
      init/glcoin-wallet.cpp
      wallet/wallettool.cpp
    )
    add_windows_resources(glcoin-wallet glcoin-wallet-res.rc)
    add_windows_application_manifest(glcoin-wallet)
    target_link_libraries(glcoin-wallet
      core_interface
      glcoin_wallet
      glcoin_common
      glcoin_util
    )
    install_binary_component(glcoin-wallet HAS_MANPAGE)
  endif()
endif()


# P2P and RPC server functionality used by `glcoind` and `glcoin-qt` executables.
add_library(glcoin_node STATIC EXCLUDE_FROM_ALL
  addrdb.cpp
  addrman.cpp
  banman.cpp
  bip324.cpp
  blockencodings.cpp
  blockfilter.cpp
  consensus/ipfscommit.cpp
  consensus/tx_verify.cpp
  dbwrapper.cpp
  deploymentstatus.cpp
  flatfile.cpp
  headerssync.cpp
  httprpc.cpp
  httpserver.cpp
  i2p.cpp
  index/base.cpp
  index/blockfilterindex.cpp
  index/coinstatsindex.cpp
  index/txindex.cpp
  index/txospenderindex.cpp
  init.cpp
  kernel/chain.cpp
  kernel/checks.cpp
  kernel/coinstats.cpp
  kernel/context.cpp
  kernel/cs_main.cpp
  kernel/disconnected_transactions.cpp
  kernel/mempool_removal_reason.cpp
  mapport.cpp
  glcsiteidx.cpp
  ipfsclient.cpp
  ipfslink.cpp
  ipfspadstore.cpp
  ipfspin.cpp
  ipfspintracker.cpp
  minerregistry.cpp
  net.cpp
  net_processing.cpp
  netgroup.cpp
  node/abort.cpp
  node/blockmanager_args.cpp
  node/blockstorage.cpp
  node/caches.cpp
  node/chainstate.cpp
  node/chainstatemanager_args.cpp
  node/coin.cpp
  node/coins_view_args.cpp
  node/connection_types.cpp
  node/context.cpp
  node/database_args.cpp
  node/eviction.cpp
  node/interface_ui.cpp
  node/interfaces.cpp
  node/kernel_notifications.cpp
  node/mempool_args.cpp
  node/mempool_persist.cpp
  node/mempool_persist_args.cpp
  node/miner.cpp
  node/mini_miner.cpp
  node/minisketchwrapper.cpp
  node/peerman_args.cpp
  node/psbt.cpp
  node/timeoffsets.cpp
  node/transaction.cpp
  node/txdownloadman_impl.cpp
  node/txorphanage.cpp
  node/txreconciliation.cpp
  node/utxo_snapshot.cpp
  node/warnings.cpp
  noui.cpp
  policy/ephemeral_policy.cpp
  policy/fees/block_policy_estimator.cpp
  policy/fees/block_policy_estimator_args.cpp
  policy/packages.cpp
  policy/rbf.cpp
  policy/settings.cpp
  policy/truc_policy.cpp
  private_broadcast.cpp
  rest.cpp
  rpc/blockchain.cpp
  rpc/external_signer.cpp
  rpc/fees.cpp
  rpc/mempool.cpp
  rpc/glce.cpp
  rpc/glcsite.cpp
  rpc/ipfslink.cpp
  rpc/minerregistry.cpp
  rpc/mining.cpp
  rpc/net.cpp
  rpc/node.cpp
  rpc/output_script.cpp
  rpc/rawtransaction.cpp
  rpc/server.cpp
  rpc/server_util.cpp
  rpc/signmessage.cpp
  rpc/txoutproof.cpp
  script/sigcache.cpp
  signet.cpp
  torcontrol.cpp
  txdb.cpp
  txgraph.cpp
  txmempool.cpp
  txrequest.cpp
  validation.cpp
  validationinterface.cpp
  versionbits.cpp
  $<$<TARGET_EXISTS:glcoin_wallet>:wallet/init.cpp>
  $<$<NOT:$<TARGET_EXISTS:glcoin_wallet>>:dummywallet.cpp>
)
target_link_libraries(glcoin_node
  PRIVATE
    core_interface
    glcoin_common
    glcoin_util
    $<TARGET_NAME_IF_EXISTS:glcoin_zmq>
    leveldb
    minisketch
    univalue
    Boost::headers
    $<TARGET_NAME_IF_EXISTS:libevent::core>
    $<TARGET_NAME_IF_EXISTS:libevent::extra>
    $<TARGET_NAME_IF_EXISTS:libevent::pthreads>
    $<TARGET_NAME_IF_EXISTS:USDT::headers>
)
if(WITH_EMBEDDED_ASMAP)
  target_compile_definitions(glcoin_node PRIVATE ENABLE_EMBEDDED_ASMAP=1)
  include(TargetDataSources)
  target_raw_data_sources(glcoin_node NAMESPACE node::data
    node/data/ip_asn.dat
  )
endif()

# Glcoin wrapper executable that can call other executables.
if(BUILD_BITCOIN_BIN)
  add_executable(glcoin glcoin.cpp)
  add_windows_resources(glcoin glcoin-res.rc)
  add_windows_application_manifest(glcoin)
  target_link_libraries(glcoin core_interface glcoin_common glcoin_util)
  install_binary_component(glcoin HAS_MANPAGE)
endif()

# Glcoin Core glcoind.
if(BUILD_DAEMON)
  add_executable(glcoind
    glcoind.cpp
    init/glcoind.cpp
  )
  add_windows_resources(glcoind glcoind-res.rc)
  add_windows_application_manifest(glcoind)
  target_link_libraries(glcoind
    core_interface
    glcoin_node
    $<TARGET_NAME_IF_EXISTS:glcoin_wallet>
  )
  install_binary_component(glcoind HAS_MANPAGE)
endif()
if(ENABLE_IPC AND BUILD_DAEMON)
  add_executable(glcoin-node
    glcoind.cpp
    init/glcoin-node.cpp
  )
  target_link_libraries(glcoin-node
    core_interface
    glcoin_node
    glcoin_ipc
    $<TARGET_NAME_IF_EXISTS:glcoin_wallet>
  )
  install_binary_component(glcoin-node INTERNAL)
endif()


add_library(glcoin_cli STATIC EXCLUDE_FROM_ALL
  compat/stdin.cpp
  rpc/client.cpp
)
target_link_libraries(glcoin_cli
  PUBLIC
    core_interface
    univalue
)


# Glcoin Core RPC client
if(BUILD_CLI)
  add_executable(glcoin-cli glcoin-cli.cpp init/basic.cpp)
  add_windows_resources(glcoin-cli glcoin-cli-res.rc)
  add_windows_application_manifest(glcoin-cli)
  target_link_libraries(glcoin-cli
    core_interface
    glcoin_cli
    glcoin_common
    glcoin_ipc
    glcoin_util
    libevent::core
    libevent::extra
  )
  install_binary_component(glcoin-cli HAS_MANPAGE)
endif()


if(BUILD_TX)
  add_executable(glcoin-tx glcoin-tx.cpp)
  add_windows_resources(glcoin-tx glcoin-tx-res.rc)
  add_windows_application_manifest(glcoin-tx)
  target_link_libraries(glcoin-tx
    core_interface
    glcoin_common
    glcoin_util
    univalue
  )
  install_binary_component(glcoin-tx HAS_MANPAGE)
endif()


if(BUILD_UTIL)
  add_executable(glcoin-util glcoin-util.cpp)
  add_windows_resources(glcoin-util glcoin-util-res.rc)
  add_windows_application_manifest(glcoin-util)
  target_link_libraries(glcoin-util
    core_interface
    glcoin_common
    glcoin_util
  )
  install_binary_component(glcoin-util HAS_MANPAGE)
endif()


if(BUILD_GUI)
  add_subdirectory(qt)
endif()


if(BUILD_KERNEL_LIB)
  add_subdirectory(kernel)
  if (BUILD_KERNEL_TEST)
    add_subdirectory(test/kernel)
  endif()
  if(BUILD_UTIL_CHAINSTATE)
    add_executable(glcoin-chainstate
      glcoin-chainstate.cpp
    )
    add_windows_application_manifest(glcoin-chainstate)
    target_link_libraries(glcoin-chainstate
      PRIVATE
        core_interface
        glcoinkernel
    )
    install_binary_component(glcoin-chainstate INTERNAL)
  endif()
endif()


add_subdirectory(test/util)
if(BUILD_BENCH)
  add_subdirectory(bench)
endif()

if(BUILD_TESTS)
  add_subdirectory(test)
endif()

if(BUILD_FUZZ_BINARY)
  add_subdirectory(test/fuzz)
endif()
