logos-delivery/waku.nimble
Prem Chaitanya Prathi d8bbef0c5b
feat(mix): bump libp2p stack to v2.0.0 + adopt stateless RLN spam protection
Combines five dep-and-build changes that all flow from the libp2p v2.0.0
upgrade and the move to the extracted libp2p_mix / mix-rln plugin stack:

waku.nimble:
  * libp2p: ff8d51857 -> c43199378 (release/v2.0.0 tip; sha-pinned until
    vacp2p cuts a v2.0.0 tag).
  * Drop the bare `zlib < 0.2` cap — no longer needed by the upgraded
    libp2p.
  * websock: bare ">= 0.4.0" — replaces the d4cd68b URL+SHA workaround
    that pinned through a libp2p commit-specific websock SHA.
  * nim-json-rpc: switch to chaitanyaprem/nim-json-rpc#f05fad25 — relaxes
    websock cap to allow >=0.4.0. TODO: revert to status-im/nim-json-rpc
    once status-im/nim-json-rpc#277 merges and a tag is cut.
  * lsquic: bare ">= 0.4.1" (drops URL form).
  * Add mix-rln-spam-protection-plugin pin (23b278b4) and nim-libp2p-mix
    pin (50c4ab4f — PR #14 HEAD); the plugin pins the same libp2p_mix
    SHA so the diamond dep collapses to a single source.

waku/factory/waku.nim:
  * Explicit HPService.setup(switch) / AutonatService.setup(switch)
    calls. libp2p v2.0.0's Service lifecycle refactor (libp2p#2462)
    removed switch.start's auto-setup loop, so any caller that assigns
    directly to switch.services (we do) is responsible for calling
    setup() themselves. Without it, AutonatService.addressMapper stays
    nil and peerInfo.expandAddrs SIGSEGVs during start(). Wrapped in
    try/except for ServiceSetupError so a setup failure surfaces as a
    logged error rather than a crash.

Build / scripts:
  * scripts/build_rln_mix.sh removed and Makefile simplified — librln
    is now a single shared archive built from zerokit's `stateless`
    features (no separate librln_mix archive).
  * simulations/mixnet/build_setup.sh + setup_credentials.nim updated
    to use librln_v2.0.2.a directly and run RLN keystore setup before
    nodes start.

Validated:
  * Cold local-cache nimble setup --localdeps -y.
  * wakunode2 and chat2mix link cleanly.
  * Mixnet roundtrip sim: [PASS] bob received message from alice.
  * RLN proof generation + verification on every in-path mix node:
    5 gen_called == 5 verified, 0 SPAM_PROOF_* errors.
2026-06-04 16:54:44 +05:30

600 lines
22 KiB
Nim

#!fmt: off
import os
mode = ScriptMode.Verbose
### Package
version = "0.38.1"
author = "Status Research & Development GmbH"
description = "Waku, Private P2P Messaging for Resource-Restricted Devices"
license = "MIT or Apache License 2.0"
const RequiredNimVersion = "2.2.4"
## This is the nim compiler version that we are working on. Other versions may behave differently.
const RequiredNimbleVersion = "0.22.3"
## Enforced nimble version to ensure a reproducible flow
### Dependencies
requires "nim >= 2.2.4",
"chronos >= 4.2.0",
"taskpools",
# Logging & Configuration
"chronicles",
"confutils",
# Serialization
"serialization",
"json_serialization",
"toml_serialization",
"faststreams",
# Networking & P2P
# nim-libp2p: release/v2.0.0 tip (c43199378). SHA-pinned because vacp2p
# hasn't published a v2.0.0 git tag yet.
"https://github.com/vacp2p/nim-libp2p.git#c43199378f46d0aaf61be1cad1ee1d63e8f665d6",
"eth",
"nat_traversal",
"dnsdisc",
"dnsclient",
"httputils >= 0.4.1",
"https://github.com/status-im/nim-websock >= 0.4.0",
# Cryptography
"nimcrypto == 0.6.4", # 0.6.4 used in libp2p. Version 0.7.3 makes test to crash on Ubuntu.
"secp256k1",
"bearssl",
# RPC & APIs
# TODO: revert to status-im/nim-json-rpc once
# https://github.com/status-im/nim-json-rpc/pull/277 merges + tag cut.
"https://github.com/chaitanyaprem/nim-json-rpc.git#f05fad251a1ceb845db963902b54295e7f37fb99",
"presto",
"web3",
# Database
"db_connector",
"sqlite3_abi",
# Utilities
"stew",
"stint",
"metrics",
"regex",
"unicodedb",
"results",
"minilru",
"zlib",
# Debug & Testing
"testutils",
"unittest2"
# Packages not on nimble (use git URLs)
requires "https://github.com/logos-messaging/nim-ffi#v0.1.3"
requires "https://github.com/logos-co/mix-rln-spam-protection-plugin.git#23b278b4ab21193ad4e9ce76015f008db7332a6f"
# nim-libp2p-mix: extracted mix protocol used by the plugin and by waku's
# mix integration layer. Tip of experiment/drop-nimble-lock (PR #14, stacked
# on chore/bump-libp2p-v2.0.0). Carries the v2.0.0 bump + sink overrides +
# AddressConfidence.Infinite + deeper move-semantics propagation + the
# lockfile-as-build-artefact cleanup. Re-bump to master SHA once #14 lands.
# The plugin pins the same SHA — keeps the diamond dep collapsed.
requires "https://github.com/logos-co/nim-libp2p-mix.git#50c4ab4fa788a33eb12a0a2cecaa708873352b58"
requires "https://github.com/logos-messaging/nim-sds.git#abdd40cc645f1b024c3ee99cced7e287c4e4c441"
requires "https://github.com/NagyZoltanPeter/nim-brokers.git#v3.1.1"
requires "lsquic >= 0.4.1"
requires "https://github.com/vacp2p/nim-jwt.git#057ec95eb5af0eea9c49bfe9025b3312c95dc5f2"
proc getMyCPU(): string =
## Need to set cpu more explicit manner to avoid arch issues between dependencies
when defined(macosx) and defined(arm64):
return " --cpu:arm64 --passC:\"-arch arm64\" --passL:\"-arch arm64\" "
elif defined(macosx) and defined(amd64):
return " --cpu:amd64 --passC:\"-arch x86_64\" --passL:\"-arch x86_64\" "
elif defined(arm64):
return " --cpu:arm64 "
elif defined(amd64):
return " --cpu:amd64 "
proc getNimParams(): string =
return " " & getEnv("NIM_PARAMS") & " "
### Helper functions
proc buildModule(filePath, params = ""): bool =
if not dirExists "build":
mkDir "build"
if not fileExists(filePath):
echo "File to build not found: " & filePath
return false
exec "nim c --out:build/" & filepath & ".bin --mm:refc " & getMyCPU() & getNimParams() & " " & params &
" " & filePath
# exec will raise exception if anything goes wrong
return true
proc buildBinary(name: string, srcDir = "./", params = "") =
if not dirExists "build":
mkDir "build"
exec "nim c --out:build/" & name & " --mm:refc " & getMyCPU() & getNimParams() & " " & params & " " &
srcDir & name & ".nim"
proc buildLibrary(lib_name: string, srcDir = "./", params = "", `type` = "static", srcFile = "libwaku.nim", mainPrefix = "libwaku") =
if not dirExists "build":
mkDir "build"
if `type` == "static":
exec "nim c" & " --out:build/" & lib_name &
" --threads:on --app:staticlib --opt:speed --noMain --mm:refc --header -d:metrics --nimMainPrefix:" & mainPrefix & " --skipParentCfg:on -d:discv5_protocol_id=d5waku " &
getMyCPU() & getNimParams() & srcDir & "/" & srcFile
else:
exec "nim c" & " --out:build/" & lib_name &
" --threads:on --app:lib --opt:speed --noMain --mm:refc --header -d:metrics --nimMainPrefix:" & mainPrefix & " --skipParentCfg:off -d:discv5_protocol_id=d5waku " &
getMyCPU() & getNimParams() & " " & srcDir & "/" & srcFile
proc buildLibDynamicWindows(libName: string, folderName: string) =
buildLibrary libName & ".dll", folderName,
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
"dynamic", libName & ".nim", libname
proc buildLibDynamicLinux(libName: string, folderName: string) =
buildLibrary libName & ".so", folderName,
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
"dynamic", libName & ".nim", libname
proc buildLibDynamicMac(libName: string, folderName: string) =
let sdkPath = staticExec("xcrun --show-sdk-path").strip()
when defined(arm64):
let archFlags = "--cpu:arm64 --passC:\"-arch arm64\" --passL:\"-arch arm64\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
elif defined(amd64):
let archFlags = "--cpu:amd64 --passC:\"-arch x86_64\" --passL:\"-arch x86_64\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
else:
{.error: "Unsupported macOS architecture".}
buildLibrary libName & ".dylib", folderName,
archFlags & " -d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE",
"dynamic", libName & ".nim", libname
proc buildLibStaticWindows(libName: string, folderName: string) =
buildLibrary libName & ".lib", folderName,
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
"static", libName & ".nim", libname
proc buildLibStaticLinux(libName: string, folderName: string) =
buildLibrary libName & ".a", folderName,
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
"static", libName & ".nim", libname
proc buildLibStaticMac(libName: string, folderName: string) =
let sdkPath = staticExec("xcrun --show-sdk-path").strip()
when defined(arm64):
let archFlags = "--cpu:arm64 --passC:\"-arch arm64\" --passL:\"-arch arm64\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
elif defined(amd64):
let archFlags = "--cpu:amd64 --passC:\"-arch x86_64\" --passL:\"-arch x86_64\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
else:
{.error: "Unsupported macOS architecture".}
buildLibrary libName & ".a", folderName,
archFlags & " -d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE",
"static", libName & ".nim", libname
### Mobile Android
proc buildMobileAndroid(srcDir = ".", params = "") =
let cpu = getEnv("CPU")
let abiDir = getEnv("ABIDIR")
let outDir = "build/android/" & abiDir
if not dirExists outDir:
mkDir outDir
exec "nim c" & " --out:" & outDir &
"/liblogosdelivery.so --threads:on --app:lib --opt:speed --noMain --mm:refc -d:chronicles_sinks=textlines[dynamic] --header -d:chronosEventEngine=epoll --passL:-L" &
outdir & " --passL:-lrln --passL:-llog --cpu:" & cpu & " --nimMainPrefix:liblogosdelivery --os:android -d:androidNDK " & params &
getNimParams() & " " & srcDir & "/liblogosdelivery.nim"
task libLogosDeliveryAndroid, "Build the mobile bindings for Android":
let srcDir = "./library"
buildMobileAndroid srcDir, "-d:chronicles_log_level=ERROR"
### Mobile iOS
import std/sequtils
proc buildMobileIOS(srcDir = ".", params = "") =
echo "Building iOS liblogosdelivery library"
let iosArch = getEnv("IOS_ARCH")
let iosSdk = getEnv("IOS_SDK")
let sdkPath = getEnv("IOS_SDK_PATH")
if sdkPath.len == 0:
quit "Error: IOS_SDK_PATH not set. Set it to the path of the iOS SDK"
# Get nimble package paths
let bearsslPath = gorge("nimble path bearssl").strip()
let secp256k1Path = gorge("nimble path secp256k1").strip()
let natTraversalPath = gorge("nimble path nat_traversal").strip()
# Get Nim standard library path
let nimPath = gorge("nim --fullhelp 2>&1 | head -1 | sed 's/.*\\[//' | sed 's/\\].*//'").strip()
let nimLibPath = nimPath.parentDir.parentDir / "lib"
# Use SDK name in path to differentiate device vs simulator
let outDir = "build/ios/" & iosSdk & "-" & iosArch
if not dirExists outDir:
mkDir outDir
var extra_params = params
let args = commandLineParams()
for arg in args:
extra_params &= " " & arg
let cpu = if iosArch == "arm64": "arm64" else: "amd64"
# The output static library
let nimcacheDir = outDir & "/nimcache"
let objDir = outDir & "/obj"
let vendorObjDir = outDir & "/vendor_obj"
let aFile = outDir & "/liblogosdelivery.a"
if not dirExists objDir:
mkDir objDir
if not dirExists vendorObjDir:
mkDir vendorObjDir
let clangBase = "clang -arch " & iosArch & " -isysroot " & sdkPath &
" -mios-version-min=18.0 -fembed-bitcode -fPIC -O2"
# Generate C sources from Nim (no linking)
exec "nim c" &
" --nimcache:" & nimcacheDir &
" --os:ios --cpu:" & cpu &
" --compileOnly:on" &
" --noMain --mm:refc" &
" --threads:on --opt:size --header" &
" -d:metrics -d:discv5_protocol_id=d5waku" &
" --nimMainPrefix:liblogosdelivery --skipParentCfg:on" &
" --cc:clang" &
" " & extra_params &
" " & srcDir & "/liblogosdelivery.nim"
# Compile vendor C libraries for iOS
# --- BearSSL ---
echo "Compiling BearSSL for iOS..."
let bearSslSrcDir = bearsslPath / "bearssl/csources/src"
let bearSslIncDir = bearsslPath / "bearssl/csources/inc"
for path in walkDirRec(bearSslSrcDir):
if path.endsWith(".c"):
let relPath = path.replace(bearSslSrcDir & "/", "").replace("/", "_")
let baseName = relPath.changeFileExt("o")
let oFile = vendorObjDir / ("bearssl_" & baseName)
if not fileExists(oFile):
exec clangBase & " -I" & bearSslIncDir & " -I" & bearSslSrcDir & " -c " & path & " -o " & oFile
# --- secp256k1 ---
echo "Compiling secp256k1 for iOS..."
let secp256k1Dir = secp256k1Path / "vendor/secp256k1"
let secp256k1Flags = " -I" & secp256k1Dir & "/include" &
" -I" & secp256k1Dir & "/src" &
" -I" & secp256k1Dir &
" -DENABLE_MODULE_RECOVERY=1" &
" -DENABLE_MODULE_ECDH=1" &
" -DECMULT_WINDOW_SIZE=15" &
" -DECMULT_GEN_PREC_BITS=4"
# Main secp256k1 source
let secp256k1Obj = vendorObjDir / "secp256k1.o"
if not fileExists(secp256k1Obj):
exec clangBase & secp256k1Flags & " -c " & secp256k1Dir & "/src/secp256k1.c -o " & secp256k1Obj
# Precomputed tables (required for ecmult operations)
let secp256k1PreEcmultObj = vendorObjDir / "secp256k1_precomputed_ecmult.o"
if not fileExists(secp256k1PreEcmultObj):
exec clangBase & secp256k1Flags & " -c " & secp256k1Dir & "/src/precomputed_ecmult.c -o " & secp256k1PreEcmultObj
let secp256k1PreEcmultGenObj = vendorObjDir / "secp256k1_precomputed_ecmult_gen.o"
if not fileExists(secp256k1PreEcmultGenObj):
exec clangBase & secp256k1Flags & " -c " & secp256k1Dir & "/src/precomputed_ecmult_gen.c -o " & secp256k1PreEcmultGenObj
# --- miniupnpc ---
echo "Compiling miniupnpc for iOS..."
let miniupnpcSrcDir = natTraversalPath / "vendor/miniupnp/miniupnpc/src"
let miniupnpcIncDir = natTraversalPath / "vendor/miniupnp/miniupnpc/include"
let miniupnpcBuildDir = natTraversalPath / "vendor/miniupnp/miniupnpc/build"
let miniupnpcFiles = @[
"addr_is_reserved.c", "connecthostport.c", "igd_desc_parse.c",
"minisoap.c", "minissdpc.c", "miniupnpc.c", "miniwget.c",
"minixml.c", "portlistingparse.c", "receivedata.c", "upnpcommands.c",
"upnpdev.c", "upnperrors.c", "upnpreplyparse.c"
]
for fileName in miniupnpcFiles:
let srcPath = miniupnpcSrcDir / fileName
let oFile = vendorObjDir / ("miniupnpc_" & fileName.changeFileExt("o"))
if fileExists(srcPath) and not fileExists(oFile):
exec clangBase &
" -I" & miniupnpcIncDir &
" -I" & miniupnpcSrcDir &
" -I" & miniupnpcBuildDir &
" -DMINIUPNPC_SET_SOCKET_TIMEOUT" &
" -D_BSD_SOURCE -D_DEFAULT_SOURCE" &
" -c " & srcPath & " -o " & oFile
# --- libnatpmp ---
echo "Compiling libnatpmp for iOS..."
let natpmpSrcDir = natTraversalPath / "vendor/libnatpmp-upstream"
# Only compile natpmp.c - getgateway.c uses net/route.h which is not available on iOS
let natpmpObj = vendorObjDir / "natpmp_natpmp.o"
if not fileExists(natpmpObj):
exec clangBase &
" -I" & natpmpSrcDir &
" -DENABLE_STRNATPMPERR" &
" -c " & natpmpSrcDir & "/natpmp.c -o " & natpmpObj
# Use iOS-specific stub for getgateway
let getgatewayStubSrc = "./library/ios_natpmp_stubs.c"
let getgatewayStubObj = vendorObjDir / "natpmp_getgateway_stub.o"
if fileExists(getgatewayStubSrc) and not fileExists(getgatewayStubObj):
exec clangBase & " -c " & getgatewayStubSrc & " -o " & getgatewayStubObj
# --- BearSSL stubs (for tools functions not in main library) ---
echo "Compiling BearSSL stubs for iOS..."
let bearSslStubsSrc = "./library/ios_bearssl_stubs.c"
let bearSslStubsObj = vendorObjDir / "bearssl_stubs.o"
if fileExists(bearSslStubsSrc) and not fileExists(bearSslStubsObj):
exec clangBase & " -c " & bearSslStubsSrc & " -o " & bearSslStubsObj
# Compile all Nim-generated C files to object files
echo "Compiling Nim-generated C files for iOS..."
var cFiles: seq[string] = @[]
for kind, path in walkDir(nimcacheDir):
if kind == pcFile and path.endsWith(".c"):
cFiles.add(path)
for cFile in cFiles:
let baseName = extractFilename(cFile).changeFileExt("o")
let oFile = objDir / baseName
exec clangBase &
" -DENABLE_STRNATPMPERR" &
" -I" & nimLibPath &
" -I" & bearsslPath & "/bearssl/csources/inc/" &
" -I" & bearsslPath & "/bearssl/csources/tools/" &
" -I" & bearsslPath & "/bearssl/abi/" &
" -I" & secp256k1Path & "/vendor/secp256k1/include/" &
" -I" & natTraversalPath & "/vendor/miniupnp/miniupnpc/include/" &
" -I" & natTraversalPath & "/vendor/libnatpmp-upstream/" &
" -I" & nimcacheDir &
" -c " & cFile &
" -o " & oFile
# Create static library from all object files
echo "Creating static library..."
var objFiles: seq[string] = @[]
for kind, path in walkDir(objDir):
if kind == pcFile and path.endsWith(".o"):
objFiles.add(path)
for kind, path in walkDir(vendorObjDir):
if kind == pcFile and path.endsWith(".o"):
objFiles.add(path)
exec "libtool -static -o " & aFile & " " & objFiles.join(" ")
echo "iOS library created: " & aFile
task libWakuIOS, "Build the mobile bindings for iOS":
let srcDir = "./library"
let extraParams = "-d:chronicles_log_level=ERROR"
buildMobileIOS srcDir, extraParams
proc test(name: string, params = "-d:chronicles_log_level=DEBUG") =
# XXX: When running `> NIM_PARAMS="-d:chronicles_log_level=INFO" make test2`
# I expect compiler flag to be overridden, however it stays with whatever is
# specified here.
buildBinary name, "tests/", params
exec "build/" & name
### Waku common tasks
task testcommon, "Build & run common tests":
test "all_tests_common", "-d:chronicles_log_level=DEBUG -d:chronosStrictException"
### Waku tasks
task wakunode2, "Build Waku v2 cli node":
let name = "wakunode2"
buildBinary name, "apps/wakunode2/", " -d:chronicles_log_level=TRACE "
task benchmarks, "Some benchmarks":
let name = "benchmarks"
buildBinary name, "apps/benchmarks/", "-p:../.."
task wakucanary, "Build waku-canary tool":
let name = "wakucanary"
buildBinary name, "apps/wakucanary/"
task networkmonitor, "Build network monitor tool":
let name = "networkmonitor"
buildBinary name, "apps/networkmonitor/"
task rln_db_inspector, "Build the rln db inspector":
let name = "rln_db_inspector"
buildBinary name, "tools/rln_db_inspector/"
task test, "Build & run Waku tests":
test "all_tests_waku"
task testwakunode2, "Build & run wakunode2 app tests":
test "all_tests_wakunode2"
task example2, "Build Waku examples":
buildBinary "api_example", "examples/api_example/"
buildBinary "publisher", "examples/"
buildBinary "subscriber", "examples/"
buildBinary "filter_subscriber", "examples/"
buildBinary "lightpush_publisher", "examples/"
task chat2, "Build example Waku chat usage":
# NOTE For debugging, set debug level. For chat usage we want minimal log
# output to STDOUT. Can be fixed by redirecting logs to file (e.g.)
#buildBinary name, "examples/", "-d:chronicles_log_level=WARN"
let name = "chat2"
buildBinary name,
"apps/chat2/",
"-d:chronicles_sinks=textlines[file] -d:chronicles_log_level=TRACE "
# -d:ssl - cause unlisted exception error in libp2p/utility...
task chat2mix, "Build example Waku chat mix usage":
# NOTE For debugging, set debug level. For chat usage we want minimal log
# output to STDOUT. Can be fixed by redirecting logs to file (e.g.)
#buildBinary name, "examples/", "-d:chronicles_log_level=WARN"
let name = "chat2mix"
buildBinary name,
"apps/chat2mix/",
"-d:chronicles_sinks=textlines[file] -d:chronicles_log_level=TRACE "
# -d:ssl - cause unlisted exception error in libp2p/utility...
task chat2bridge, "Build chat2bridge":
let name = "chat2bridge"
buildBinary name, "apps/chat2bridge/"
task liteprotocoltester, "Build liteprotocoltester":
let name = "liteprotocoltester"
buildBinary name, "apps/liteprotocoltester/", "-d:chronicles_log_level=TRACE"
task lightpushwithmix, "Build lightpushwithmix":
let name = "lightpush_publisher_mix"
buildBinary name, "examples/lightpush_mix/"
task buildTest, "Test custom target":
let args = commandLineParams()
if args.len == 0:
quit "Missing test file"
let filepath = args[^1]
discard buildModule(filepath)
import std/strutils
task execTest, "Run test":
let args = commandLineParams()
if args.len == 0:
quit "Missing arguments"
# expects: <file> "<test name>"
let filepath =
if args.len >= 2: args[^2]
else: args[^1]
var testSuite =
if args.len >= 1: args[^1].strip(chars = {'\"'})
else: ""
if testSuite != "":
testSuite = " \"" & testSuite & "\""
exec "build/" & filepath & ".bin " & testSuite
### C Bindings
let chroniclesParams =
"-d:chronicles_line_numbers " & "-d:chronicles_runtime_filtering=on " &
"""-d:chronicles_sinks="textlines,json" """ &
"-d:chronicles_default_output_device=Dynamic " &
"""-d:chronicles_disabled_topics="eth,dnsdisc.client" """ & "--warning:Deprecated:off " &
"--warning:UnusedImport:on " & "-d:chronicles_log_level=TRACE"
## Libwaku build tasks
task libwakuDynamicWindows, "Generate bindings":
buildLibDynamicWindows("libwaku", "library")
task libwakuDynamicLinux, "Generate bindings":
buildLibDynamicLinux("libwaku", "library")
task libwakuDynamicMac, "Generate bindings":
buildLibDynamicMac("libwaku", "library")
task libwakuStaticWindows, "Generate bindings":
buildLibStaticWindows("libwaku", "library")
task libwakuStaticLinux, "Generate bindings":
buildLibStaticLinux("libwaku", "library")
task libwakuStaticMac, "Generate bindings":
buildLibStaticMac("libwaku", "library")
## Liblogosdelivery build tasks
task liblogosdeliveryDynamicWindows, "Generate bindings":
buildLibDynamicWindows("liblogosdelivery", "liblogosdelivery")
task liblogosdeliveryDynamicLinux, "Generate bindings":
buildLibDynamicLinux("liblogosdelivery", "liblogosdelivery")
task liblogosdeliveryDynamicMac, "Generate bindings":
buildLibDynamicMac("liblogosdelivery", "liblogosdelivery")
task liblogosdeliveryStaticWindows, "Generate bindings":
buildLibStaticWindows("liblogosdelivery", "liblogosdelivery")
task liblogosdeliveryStaticLinux, "Generate bindings":
buildLibStaticLinux("liblogosdelivery", "liblogosdelivery")
task liblogosdeliveryStaticMac, "Generate bindings":
buildLibStaticMac("liblogosdelivery", "liblogosdelivery")
### Formatting tasks
task nphchanges, "Run nph on .nim/.nims/.nimble files changed on this branch/PR":
## Formats every Nim source file that differs from the base branch.
## The set covers committed changes on the branch, working-tree edits
## (staged or not) and untracked files. The base branch is auto-detected
## (origin's default branch, else local main/master); override it with
## the NPH_BASE_BRANCH env var.
let nph =
if findExe("nph").len > 0: findExe("nph")
else: getHomeDir() / ".nimble" / "bin" / "nph"
if not fileExists(nph):
quit "nph not found. Run `make build-nph` first.", 1
proc detectBaseBranch(): string =
# Explicit override wins.
if existsEnv("NPH_BASE_BRANCH"):
return getEnv("NPH_BASE_BRANCH")
# origin's default branch, e.g. "origin/main" -> "main".
let (head, hCode) =
gorgeEx("git symbolic-ref --short refs/remotes/origin/HEAD")
if hCode == 0 and head.strip().len > 0:
let parts = head.strip().split('/')
return parts[^1]
# Fall back to whichever local branch exists.
for candidate in ["main", "master"]:
let (_, vCode) =
gorgeEx("git rev-parse --verify --quiet " & candidate)
if vCode == 0:
return candidate
return "master"
let baseBranch = detectBaseBranch()
# Diff against the merge-base so we only touch what this branch introduced.
var diffRef = baseBranch
let (mergeBase, mbCode) = gorgeEx("git merge-base HEAD " & baseBranch)
if mbCode == 0 and mergeBase.strip().len > 0:
diffRef = mergeBase.strip()
let (changed, dCode) = gorgeEx("git diff --name-only --diff-filter=ACMR " & diffRef)
if dCode != 0:
quit "git diff failed: " & changed, 1
let (untracked, _) = gorgeEx("git ls-files --others --exclude-standard")
var files: seq[string]
for line in (changed & "\n" & untracked).splitLines():
let f = line.strip()
if f.len == 0:
continue
if not (f.endsWith(".nim") or f.endsWith(".nims") or f.endsWith(".nimble")):
continue
if fileExists(f) and f notin files:
files.add(f)
if files.len == 0:
echo "nphchanges: no changed .nim/.nims/.nimble files to format"
return
echo "nphchanges: formatting " & $files.len & " file(s) (base: " & baseBranch & ")"
for f in files:
echo "Formatting " & f
exec nph & " \"" & f & "\""