cmake_minimum_required(VERSION 3.20) project(naut_torrent C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option(NAUT_STANDALONE "Statically embed Jansson and Lua in the daemon and client" OFF) option(NAUT_NATIVE "Optimize Release builds for the build machine's CPU" OFF) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() add_compile_definitions(_GNU_SOURCE) add_compile_options(-Wall -Wextra -Wshadow -Wvla -Wpointer-arith -fno-omit-frame-pointer) set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") if(NAUT_NATIVE) add_compile_options($<$:-march=native>) endif() # Sanitizer convenience build: -DNAUT_SAN=address|thread|undefined if(NAUT_SAN) add_compile_options(-fsanitize=${NAUT_SAN} -g) add_link_options(-fsanitize=${NAUT_SAN}) endif() include_directories(${CMAKE_SOURCE_DIR}/include) # --- liburing (Phase 1 platform backend) ------------------------------------ find_library(URING_LIB uring) find_path(URING_INC liburing.h) if(NOT URING_LIB OR NOT URING_INC) message(FATAL_ERROR "liburing not found (install liburing-dev)") endif() find_package(OpenSSL REQUIRED COMPONENTS Crypto) if(NAUT_STANDALONE) include(FetchContent) # Jansson 2.14.1 predates CMake 4's removal of pre-3.5 policy defaults. set(CMAKE_POLICY_VERSION_MINIMUM 3.5) set(JANSSON_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) set(JANSSON_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(JANSSON_EXAMPLES OFF CACHE BOOL "" FORCE) set(JANSSON_INSTALL OFF CACHE BOOL "" FORCE) FetchContent_Declare(jansson URL https://github.com/akheron/jansson/archive/refs/tags/v2.14.1.tar.gz URL_HASH SHA256=979210eaffdffbcf54cfc34d047fccde13f21b529a381df26db871d886f729a4 DOWNLOAD_EXTRACT_TIMESTAMP TRUE) FetchContent_MakeAvailable(jansson) target_include_directories(jansson INTERFACE ${jansson_SOURCE_DIR}/src ${jansson_BINARY_DIR}/include) FetchContent_Declare(lua URL https://www.lua.org/ftp/lua-5.4.8.tar.gz URL_HASH SHA256=4f18ddae154e793e46eeab727c59ef1c0c0c2b744e7b94219710d76f530629ae DOWNLOAD_EXTRACT_TIMESTAMP TRUE SOURCE_SUBDIR cmake-unused) FetchContent_MakeAvailable(lua) set(LUA_SRC_DIR ${lua_SOURCE_DIR}/src) add_library(naut_lua STATIC ${LUA_SRC_DIR}/lapi.c ${LUA_SRC_DIR}/lauxlib.c ${LUA_SRC_DIR}/lbaselib.c ${LUA_SRC_DIR}/lcode.c ${LUA_SRC_DIR}/lcorolib.c ${LUA_SRC_DIR}/lctype.c ${LUA_SRC_DIR}/ldblib.c ${LUA_SRC_DIR}/ldebug.c ${LUA_SRC_DIR}/ldo.c ${LUA_SRC_DIR}/ldump.c ${LUA_SRC_DIR}/lfunc.c ${LUA_SRC_DIR}/lgc.c ${LUA_SRC_DIR}/linit.c ${LUA_SRC_DIR}/liolib.c ${LUA_SRC_DIR}/llex.c ${LUA_SRC_DIR}/lmathlib.c ${LUA_SRC_DIR}/lmem.c ${LUA_SRC_DIR}/loadlib.c ${LUA_SRC_DIR}/lobject.c ${LUA_SRC_DIR}/lopcodes.c ${LUA_SRC_DIR}/loslib.c ${LUA_SRC_DIR}/lparser.c ${LUA_SRC_DIR}/lstate.c ${LUA_SRC_DIR}/lstring.c ${LUA_SRC_DIR}/lstrlib.c ${LUA_SRC_DIR}/ltable.c ${LUA_SRC_DIR}/ltablib.c ${LUA_SRC_DIR}/ltm.c ${LUA_SRC_DIR}/lundump.c ${LUA_SRC_DIR}/lutf8lib.c ${LUA_SRC_DIR}/lvm.c ${LUA_SRC_DIR}/lzio.c) target_compile_definitions(naut_lua PRIVATE LUA_USE_LINUX) target_include_directories(naut_lua PUBLIC ${LUA_SRC_DIR}) target_link_libraries(naut_lua PUBLIC m ${CMAKE_DL_LIBS}) set(NAUT_JANSSON_TARGET jansson) set(NAUT_LUA_TARGET naut_lua) else() find_package(PkgConfig REQUIRED) pkg_check_modules(JANSSON REQUIRED IMPORTED_TARGET jansson) pkg_check_modules(LUA REQUIRED IMPORTED_TARGET lua) set(NAUT_JANSSON_TARGET PkgConfig::JANSSON) set(NAUT_LUA_TARGET PkgConfig::LUA) endif() # --- core: zero-dependency foundation --------------------------------------- add_library(naut_core STATIC src/core/common.c src/core/buf.c src/core/mpmc.c src/core/bitfield.c src/core/log.c src/core/worker.c ) target_link_libraries(naut_core PUBLIC pthread) # --- crypto: hashing + stream cipher (throughput-critical) ------------------ add_library(naut_crypto STATIC src/crypto/sha1.c src/crypto/sha256.c src/crypto/rc4.c src/crypto/merkle.c ) target_link_libraries(naut_crypto PUBLIC naut_core) # --- bencode: parser/encoder (fuzz target) ---------------------------------- add_library(naut_bencode STATIC src/bencode/bencode.c) target_link_libraries(naut_bencode PUBLIC naut_core) # --- metainfo: .torrent + magnet parsing ------------------------------------ add_library(naut_metainfo STATIC src/metainfo/metainfo.c src/metainfo/magnet.c) target_link_libraries(naut_metainfo PUBLIC naut_bencode naut_crypto) # --- tracker: HTTP + UDP announce (codec + blocking fetch) ------------------ add_library(naut_tracker STATIC src/tracker/tracker.c src/tracker/udp.c src/tracker/fetch.c) target_link_libraries(naut_tracker PUBLIC naut_bencode) # --- dht: BEP-5 KRPC codec + bounded iterative peer lookup ------------------ add_library(naut_dht STATIC src/dht/dht.c src/dht/fetch.c) target_link_libraries(naut_dht PUBLIC naut_bencode naut_tracker) # --- peer: wire protocol codec (sans-IO) ------------------------------------ add_library(naut_peer STATIC src/peer/wire.c src/peer/extension.c src/peer/metadata.c src/peer/pipeline.c) target_link_libraries(naut_peer PUBLIC naut_core naut_crypto naut_bencode naut_tracker m) # MSE is optional at the application boundary and is the only OpenSSL user. add_library(naut_mse STATIC src/peer/mse.c) target_link_libraries(naut_mse PUBLIC naut_peer OpenSSL::Crypto) # --- storage: file backend -------------------------------------------------- add_library(naut_storage STATIC src/storage/storage.c) target_link_libraries(naut_storage PUBLIC naut_core naut_metainfo) # --- piece: download state machine (request/assemble/verify/persist) -------- add_library(naut_piece STATIC src/piece/piece.c) target_link_libraries(naut_piece PUBLIC naut_storage naut_crypto naut_metainfo) # --- platform: the only code that touches the kernel ------------------------ add_library(naut_platform STATIC src/platform/uring.c src/platform/net.c src/platform/system.c ) target_include_directories(naut_platform PUBLIC ${URING_INC}) target_link_libraries(naut_platform PUBLIC naut_core ${URING_LIB}) # CPU topology helpers do not require the io_uring platform backend. add_library(naut_system STATIC src/platform/system.c) target_link_libraries(naut_system PUBLIC naut_core) # --- session + extensibility control plane --------------------------------- add_library(naut_session STATIC src/session/event.c) target_link_libraries(naut_session PUBLIC naut_core) # torrent registry: maps control-plane ids -> storage (move_file resolution) add_library(naut_torrents STATIC src/session/session.c) target_link_libraries(naut_torrents PUBLIC naut_storage) add_library(naut_rpc STATIC src/rpc/rpc.c) target_link_libraries(naut_rpc PUBLIC naut_session naut_core ${NAUT_JANSSON_TARGET}) add_library(naut_plugin STATIC src/plugin/plugin.c) target_link_libraries(naut_plugin PUBLIC naut_rpc naut_session dl) add_library(naut_script STATIC src/script/script.c) target_link_libraries(naut_script PUBLIC naut_session naut_core ${NAUT_LUA_TARGET}) add_library(naut_example MODULE plugins/example/example.c) target_include_directories(naut_example PRIVATE ${CMAKE_SOURCE_DIR}/include) set_target_properties(naut_example PROPERTIES PREFIX "") add_library(naut_webui MODULE plugins/webui/webui.c) target_include_directories(naut_webui PRIVATE ${CMAKE_SOURCE_DIR}/include) target_link_libraries(naut_webui PRIVATE ${NAUT_JANSSON_TARGET} pthread) set_target_properties(naut_webui PROPERTIES PREFIX "") # --- echo: Phase 1 gate (io_uring echo server on the buffer pool) ----------- # add_executable(naut_echo apps/echo/main.c) # target_link_libraries(naut_echo PRIVATE naut_platform naut_core) # --- leech: Phase 3 gate (single-peer download, byte-correct + verified) ---- # add_executable(naut_leech apps/leech/main.c) # target_link_libraries(naut_leech PRIVATE # naut_piece naut_peer naut_mse naut_metainfo) # --- swarm: Phase 4 gate (multi-peer download, rarest-first + endgame) ------- add_library(naut_swarm_engine STATIC apps/swarm/main.c) target_compile_definitions(naut_swarm_engine PRIVATE NAUT_SWARM_LIBRARY) target_link_libraries(naut_swarm_engine PUBLIC naut_piece naut_peer naut_metainfo naut_tracker naut_dht naut_system naut_session) # add_executable(naut_swarm apps/swarm/main.c) # target_link_libraries(naut_swarm PRIVATE # naut_piece naut_peer naut_metainfo naut_tracker naut_dht naut_system # naut_session) # --- daemon + CLI: Phase 7 extensibility surface --------------------------- add_executable(nautd apps/nautd/main.c) target_link_libraries(nautd PRIVATE naut_plugin naut_script naut_rpc naut_session naut_metainfo naut_swarm_engine) add_executable(nautctl apps/nautctl/main.c) target_link_libraries(nautctl PRIVATE naut_rpc) # --- tests ------------------------------------------------------------------ enable_testing() foreach(t test_buf test_mpmc test_bitfield) add_executable(${t} tests/unit/${t}.c) target_link_libraries(${t} PRIVATE naut_core) add_test(NAME ${t} COMMAND ${t}) endforeach() add_executable(test_worker tests/unit/test_worker.c) target_link_libraries(test_worker PRIVATE naut_core naut_crypto) add_test(NAME test_worker COMMAND test_worker) add_executable(test_pipeline tests/unit/test_pipeline.c) target_link_libraries(test_pipeline PRIVATE naut_peer) add_test(NAME test_pipeline COMMAND test_pipeline) add_executable(test_rpc tests/unit/test_rpc.c) target_link_libraries(test_rpc PRIVATE naut_rpc) add_test(NAME test_rpc COMMAND test_rpc) add_executable(test_plugin tests/unit/test_plugin.c) target_link_libraries(test_plugin PRIVATE naut_plugin) target_compile_definitions(test_plugin PRIVATE NAUT_EXAMPLE_PLUGIN="$") add_dependencies(test_plugin naut_example) add_test(NAME test_plugin COMMAND test_plugin) add_executable(test_script tests/unit/test_script.c) target_link_libraries(test_script PRIVATE naut_script) target_compile_definitions(test_script PRIVATE NAUT_PHASE7_SCRIPT="${CMAKE_SOURCE_DIR}/tests/fixtures/phase7.lua") add_test(NAME test_script COMMAND test_script) # --- benchmarks ------------------------------------------------------------- add_executable(bench_hash tests/bench/bench_hash.c) target_link_libraries(bench_hash PRIVATE naut_crypto) add_executable(bench_scale tests/bench/bench_scale.c) target_link_libraries(bench_scale PRIVATE naut_core naut_crypto) # --- fuzz-lite: mutational fuzzer (run under -DNAUT_SAN=address for value) --- add_executable(fuzz_lite tests/fuzz/fuzz_lite.c) target_link_libraries(fuzz_lite PRIVATE naut_metainfo) add_executable(test_bencode tests/unit/test_bencode.c) target_link_libraries(test_bencode PRIVATE naut_bencode) add_test(NAME test_bencode COMMAND test_bencode) add_executable(test_metainfo tests/unit/test_metainfo.c) target_link_libraries(test_metainfo PRIVATE naut_metainfo) target_compile_definitions(test_metainfo PRIVATE NAUT_FIXTURES="${CMAKE_SOURCE_DIR}/tests/fixtures") add_test(NAME test_metainfo COMMAND test_metainfo) add_executable(test_peer tests/unit/test_peer.c) target_link_libraries(test_peer PRIVATE naut_peer) add_test(NAME test_peer COMMAND test_peer) add_executable(test_extension tests/unit/test_extension.c) target_link_libraries(test_extension PRIVATE naut_peer) add_test(NAME test_extension COMMAND test_extension) add_executable(test_mse tests/unit/test_mse.c) target_link_libraries(test_mse PRIVATE naut_mse) add_test(NAME test_mse COMMAND test_mse) add_executable(test_tracker tests/unit/test_tracker.c) target_link_libraries(test_tracker PRIVATE naut_tracker) add_test(NAME test_tracker COMMAND test_tracker) add_executable(test_dht tests/unit/test_dht.c) target_link_libraries(test_dht PRIVATE naut_dht) add_test(NAME test_dht COMMAND test_dht) add_executable(test_storage tests/unit/test_storage.c) target_link_libraries(test_storage PRIVATE naut_storage) add_test(NAME test_storage COMMAND test_storage) add_executable(test_download tests/unit/test_download.c) target_link_libraries(test_download PRIVATE naut_piece) target_compile_definitions(test_download PRIVATE NAUT_FIXTURES="${CMAKE_SOURCE_DIR}/tests/fixtures") add_test(NAME test_download COMMAND test_download) add_executable(test_filemove tests/unit/test_filemove.c) target_link_libraries(test_filemove PRIVATE naut_piece) target_compile_definitions(test_filemove PRIVATE NAUT_FIXTURES="${CMAKE_SOURCE_DIR}/tests/fixtures") add_test(NAME test_filemove COMMAND test_filemove) add_executable(test_picker tests/unit/test_picker.c) target_link_libraries(test_picker PRIVATE naut_piece) add_test(NAME test_picker COMMAND test_picker) # Phase 3 interop gate: download from a real libtorrent seed (SKIPs without it). # These gates exercise the standalone naut_leech/naut_swarm/naut_echo binaries, # which are currently folded into the daemon — register them only when built. if(TARGET naut_leech) add_test(NAME interop_leech COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_interop.sh $) set_tests_properties(interop_leech PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 180) add_test(NAME interop_mse COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_mse.sh $) set_tests_properties(interop_mse PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) endif() if(TARGET naut_swarm) add_test(NAME interop_magnet_dht COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_magnet_dht.sh $) set_tests_properties(interop_magnet_dht PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) # Phase 4 interop gate: both libtorrent seeds must contribute to one download. add_test(NAME interop_swarm COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_swarm.sh $) set_tests_properties(interop_swarm PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) add_test(NAME interop_tracker_swarm COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_tracker_swarm.sh $ http) set_tests_properties(interop_tracker_swarm PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) add_test(NAME interop_udp_tracker_swarm COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_tracker_swarm.sh $ udp) set_tests_properties(interop_udp_tracker_swarm PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) endif() if(TARGET naut_echo) add_test(NAME interop_echo_scale COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_echo_scale.sh $) set_tests_properties(interop_echo_scale PROPERTIES TIMEOUT 30) endif() add_test(NAME phase7_extensibility COMMAND bash ${CMAKE_SOURCE_DIR}/tests/integration/run_phase7.sh $ $ $ ${CMAKE_SOURCE_DIR}/tests/fixtures/phase7.lua) set_tests_properties(phase7_extensibility PROPERTIES TIMEOUT 15) set_tests_properties(phase7_extensibility PROPERTIES SKIP_RETURN_CODE 77) # Example Lua scripts: parser battery + end-to-end sort path building. Only # registered when a standalone lua interpreter is available. find_program(LUA_BIN NAMES lua lua5.5 lua5.4 lua5.3) if(LUA_BIN) add_test(NAME example_anitomy COMMAND ${LUA_BIN} ${CMAKE_SOURCE_DIR}/examples/test_anitomy.lua) add_test(NAME example_anime_sort COMMAND ${LUA_BIN} ${CMAKE_SOURCE_DIR}/examples/test_anime_sort.lua) endif() add_executable(test_crypto tests/unit/test_crypto.c) target_link_libraries(test_crypto PRIVATE naut_crypto) add_test(NAME test_crypto COMMAND test_crypto) # Same vectors, scalar SHA-256 path forced, to prove both backends agree. add_test(NAME test_crypto_scalar COMMAND test_crypto) set_tests_properties(test_crypto_scalar PROPERTIES ENVIRONMENT "NAUT_NO_SHANI=1")