mirror of
https://github.com/logos-messaging/nim-sds.git
synced 2026-05-17 23:49:31 +00:00
* adapt arch and cpu flags and fix ios build * require chronos 4.2.0 or higher * Android fixes and rm Makefile * enable long paths in git windows ci
314 lines
11 KiB
Nim
314 lines
11 KiB
Nim
import strutils, os
|
|
|
|
# Package
|
|
version = "0.2.4"
|
|
author = "Logos Messaging Team"
|
|
description = "E2E Scalable Data Sync API"
|
|
license = "MIT"
|
|
srcDir = "sds"
|
|
|
|
# Dependencies
|
|
requires "nim >= 2.2.4"
|
|
requires "chronos >= 4.0.4"
|
|
requires "libp2p >= 1.15.2"
|
|
requires "chronicles"
|
|
requires "stew"
|
|
requires "stint"
|
|
requires "metrics"
|
|
requires "results"
|
|
requires "taskpools >= 0.1.0" ## This should be removed when using nim-ffi dependency
|
|
|
|
proc buildLibrary(
|
|
outLibNameAndExt: string,
|
|
name: string,
|
|
srcDir = "./",
|
|
extra_params = "",
|
|
`type` = "static",
|
|
) =
|
|
if not dirExists "build":
|
|
mkDir "build"
|
|
|
|
if `type` == "static":
|
|
exec "nim c" & " --out:build/" & outLibNameAndExt &
|
|
" --threads:on --app:staticlib --opt:size --noMain --mm:refc --header --nimMainPrefix:libsds " &
|
|
extra_params & " " & srcDir & name & ".nim"
|
|
else:
|
|
when defined(windows):
|
|
exec "nim c" & " --out:build/" & outLibNameAndExt &
|
|
" --threads:on --app:lib --opt:size --noMain --mm:refc --header --nimMainPrefix:libsds " &
|
|
extra_params & " " & srcDir & name & ".nim"
|
|
else:
|
|
exec "nim c" & " --out:build/" & outLibNameAndExt &
|
|
" --threads:on --app:lib --opt:size --noMain --mm:refc --header --nimMainPrefix:libsds " &
|
|
extra_params & " " & srcDir & name & ".nim"
|
|
|
|
proc getMyCpu(): string =
|
|
## Returns a Nim-compatible CPU name (e.g. amd64, arm64) for the host.
|
|
## Respects the ARCH environment variable when set.
|
|
let envArch = getEnv("ARCH")
|
|
if envArch != "":
|
|
return envArch
|
|
when defined(arm64):
|
|
return "arm64"
|
|
elif defined(amd64):
|
|
return "amd64"
|
|
else:
|
|
let (archFromUname, _) = gorgeEx("uname -m")
|
|
let a = archFromUname.strip()
|
|
return
|
|
if a == "x86_64":
|
|
"amd64"
|
|
elif a == "aarch64":
|
|
"arm64"
|
|
else:
|
|
a
|
|
|
|
# Tasks
|
|
task test, "Run the test suite":
|
|
exec "nim c -r tests/test_bloom.nim"
|
|
exec "nim c -r tests/test_reliability.nim"
|
|
|
|
task libsdsDynamicWindows, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.dll"
|
|
let name = "libsds"
|
|
buildLibrary outLibNameAndExt,
|
|
name, "library/",
|
|
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
|
|
"dynamic"
|
|
|
|
task libsdsDynamicLinux, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.so"
|
|
let name = "libsds"
|
|
buildLibrary outLibNameAndExt,
|
|
name, "library/",
|
|
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
|
|
"dynamic"
|
|
|
|
task libsdsDynamicMac, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.dylib"
|
|
let name = "libsds"
|
|
|
|
let cpu = getMyCpu()
|
|
let clangArch = if cpu == "amd64": "x86_64" else: cpu
|
|
let sdkPath = staticExec("xcrun --show-sdk-path").strip()
|
|
let archFlags =
|
|
"--cpu:" & cpu & " --passC:\"-arch " & clangArch & "\" --passL:\"-arch " & clangArch &
|
|
"\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
|
|
buildLibrary outLibNameAndExt,
|
|
name,
|
|
"library/",
|
|
archFlags &
|
|
" -d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE",
|
|
"dynamic"
|
|
|
|
task libsdsStaticWindows, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.lib"
|
|
let name = "libsds"
|
|
buildLibrary outLibNameAndExt,
|
|
name, "library/",
|
|
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
|
|
"static"
|
|
|
|
task libsdsStaticLinux, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.a"
|
|
let name = "libsds"
|
|
buildLibrary outLibNameAndExt,
|
|
name, "library/",
|
|
"""-d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE """,
|
|
"static"
|
|
|
|
task libsdsStaticMac, "Generate bindings":
|
|
let outLibNameAndExt = "libsds.a"
|
|
let name = "libsds"
|
|
|
|
let cpu = getMyCpu()
|
|
let clangArch = if cpu == "amd64": "x86_64" else: cpu
|
|
let sdkPath = staticExec("xcrun --show-sdk-path").strip()
|
|
let archFlags =
|
|
"--cpu:" & cpu & " --passC:\"-arch " & clangArch & "\" --passL:\"-arch " & clangArch &
|
|
"\" --passC:\"-isysroot " & sdkPath & "\" --passL:\"-isysroot " & sdkPath & "\""
|
|
buildLibrary outLibNameAndExt,
|
|
name,
|
|
"library/",
|
|
archFlags &
|
|
" -d:chronicles_line_numbers --warning:Deprecated:off --warning:UnusedImport:on -d:chronicles_log_level=TRACE",
|
|
"static"
|
|
|
|
# Build Mobile iOS
|
|
proc buildMobileIOS(srcDir = ".", sdkPath = "") =
|
|
echo "Building iOS libsds library"
|
|
|
|
let outDir = "build"
|
|
let nimcacheDir = outDir & "/nimcache"
|
|
if dirExists nimcacheDir:
|
|
rmDir nimcacheDir
|
|
if not dirExists outDir:
|
|
mkDir outDir
|
|
|
|
if sdkPath.len == 0:
|
|
quit "Error: Xcode/iOS SDK not found"
|
|
|
|
let aFile = outDir & "/libsds.a"
|
|
let aFileTmp = outDir & "/libsds_tmp.a"
|
|
let cpu = getMyCpu()
|
|
let clangArch = if cpu == "amd64": "x86_64" else: cpu
|
|
|
|
# 1) Generate C sources from Nim (no linking)
|
|
# Use unique symbol prefix to avoid conflicts with other Nim libraries
|
|
exec "nim c" & " --nimcache:" & nimcacheDir & " --os:ios --cpu:" & cpu &
|
|
" --compileOnly:on" & " --noMain --mm:refc" & " --threads:on --opt:size --header" &
|
|
" --nimMainPrefix:libsds" & " --cc:clang" & " -d:useMalloc" & " " & srcDir &
|
|
"/libsds.nim"
|
|
|
|
# 2) Compile all generated C files to object files with hidden visibility
|
|
# This prevents symbol conflicts with other Nim libraries (e.g., libnim_status_client)
|
|
# Locate nimbase.h: try next to the nim binary first (jiro4989/setup-nim-action
|
|
# puts nim at .nim_runtime/bin/nim with lib/ alongside), then fall back to the
|
|
# choosenim toolchain directory (~/.choosenim/toolchains/nim-VERSION/lib/).
|
|
let (nimBin, _) = gorgeEx("which nim")
|
|
let nimLibFromBin = parentDir(parentDir(nimBin.strip())) / "lib"
|
|
let nimLibChoosenim = getHomeDir() / ".choosenim/toolchains/nim-" & NimVersion & "/lib"
|
|
let nimLibDir =
|
|
if fileExists(nimLibFromBin / "nimbase.h"): nimLibFromBin
|
|
else: nimLibChoosenim
|
|
let clangFlags =
|
|
"-arch " & clangArch & " -isysroot " & sdkPath & " -I" & nimLibDir &
|
|
" -fembed-bitcode -miphoneos-version-min=16.2 -O2" & " -fvisibility=hidden"
|
|
|
|
var objectFiles: seq[string] = @[]
|
|
for cFile in listFiles(nimcacheDir):
|
|
if cFile.endsWith(".c"):
|
|
let oFile = cFile.changeFileExt("o")
|
|
exec "clang " & clangFlags & " -c " & cFile & " -o " & oFile
|
|
objectFiles.add(oFile)
|
|
|
|
# 3) Create static library from all object files
|
|
exec "ar rcs " & aFileTmp & " " & objectFiles.join(" ")
|
|
|
|
# 4) Use libtool to localize all non-public symbols
|
|
# Keep only Sds* functions as global, hide everything else to prevent conflicts
|
|
# with nim runtime symbols from libnim_status_client
|
|
let keepSymbols =
|
|
"_Sds*:_libsdsNimMain:_libsdsDatInit*:_libsdsInit*:_NimMainModule__libsds*"
|
|
exec "xcrun libtool -static -o " & aFile & " " & aFileTmp &
|
|
" -exported_symbols_list /dev/stdin <<< '" & keepSymbols & "' 2>/dev/null || cp " &
|
|
aFileTmp & " " & aFile
|
|
|
|
echo "✔ iOS library created: " & aFile
|
|
|
|
task libsdsIOS, "Build the mobile bindings for iOS":
|
|
let srcDir = "./library"
|
|
var sdkPath = getEnv("IOS_SDK_PATH")
|
|
if sdkPath.len == 0:
|
|
let (detected, exitCode) = gorgeEx("xcrun --show-sdk-path --sdk iphoneos")
|
|
if exitCode == 0:
|
|
sdkPath = detected.strip()
|
|
buildMobileIOS srcDir, sdkPath
|
|
|
|
### Mobile Android
|
|
proc checkAndroidNdk() =
|
|
let ndkRoot = getEnv("ANDROID_NDK_ROOT")
|
|
if ndkRoot.len == 0:
|
|
quit """Error: ANDROID_NDK_ROOT is not set."""
|
|
if not dirExists(ndkRoot):
|
|
quit "Error: ANDROID_NDK_ROOT points to a non-existent directory: " & ndkRoot
|
|
# source.properties contains Pkg.Revision — present in every NDK since r10.
|
|
let propsFile = ndkRoot / "source.properties"
|
|
if not fileExists(propsFile):
|
|
quit "Error: " & ndkRoot & " does not look like a valid NDK (source.properties not found)."
|
|
let (props, _) = gorgeEx("cat " & propsFile)
|
|
var revision = ""
|
|
for line in props.splitLines():
|
|
if line.startsWith("Pkg.Revision"):
|
|
let parts = line.split('=')
|
|
if parts.len == 2:
|
|
revision = parts[1].strip()
|
|
if revision.len == 0:
|
|
quit "Error: Could not read NDK version from " & propsFile
|
|
echo "Android NDK version: " & revision
|
|
|
|
proc buildMobileAndroid(srcDir = ".", extra_params = "") =
|
|
let cpu = getMyCpu()
|
|
let ndkRoot = getEnv("ANDROID_NDK_ROOT")
|
|
let androidTarget = "30"
|
|
|
|
# Map Nim CPU name → NDK target triple and include dirname.
|
|
let (androidArch, archDirname) =
|
|
if cpu == "arm64": ("aarch64-linux-android", "aarch64-linux-android")
|
|
elif cpu == "amd64": ("x86_64-linux-android", "x86_64-linux-android")
|
|
elif cpu == "i386": ("i686-linux-android", "i686-linux-android")
|
|
else: ("armv7a-linux-androideabi","arm-linux-androideabi")
|
|
|
|
# NDK prebuilt toolchain — location differs by host OS.
|
|
let (hostOS, _) = gorgeEx("uname -s")
|
|
let ndkHostTag =
|
|
if hostOS.strip() == "Darwin": "darwin-x86_64"
|
|
else: "linux-x86_64"
|
|
let toolchainDir = ndkRoot / "toolchains/llvm/prebuilt" / ndkHostTag
|
|
let sysroot = toolchainDir / "sysroot"
|
|
let ndkClang = toolchainDir / "bin" / (androidArch & androidTarget & "-clang")
|
|
|
|
let outDir = "build"
|
|
if not dirExists outDir:
|
|
mkDir outDir
|
|
|
|
exec "nim c" &
|
|
" --out:" & outDir & "/libsds.so" &
|
|
" --threads:on --app:lib --opt:size --noMain --mm:refc --nimMainPrefix:libsds" &
|
|
" --cc:clang" &
|
|
" --clang.exe:\"" & ndkClang & "\"" &
|
|
" --clang.linkerexe:\"" & ndkClang & "\"" &
|
|
" --cpu:" & cpu &
|
|
" --os:android" &
|
|
" -d:androidNDK" &
|
|
" -d:chronosEventEngine=epoll" &
|
|
" --passC:\"--sysroot=" & sysroot & "\"" &
|
|
" --passL:\"--sysroot=" & sysroot & "\"" &
|
|
" --passC:\"--target=" & androidArch & androidTarget & "\"" &
|
|
" --passL:\"--target=" & androidArch & androidTarget & "\"" &
|
|
" --passC:\"-I" & sysroot & "/usr/include\"" &
|
|
" --passC:\"-I" & sysroot & "/usr/include/" & archDirname & "\"" &
|
|
" --passL:\"-L" & sysroot & "/usr/lib/" & archDirname & "/" & androidTarget & "\"" &
|
|
" --passL:-llog" &
|
|
" -d:chronicles_sinks=textlines[dynamic]" &
|
|
" --header" &
|
|
" " & extra_params &
|
|
" " & srcDir & "/libsds.nim"
|
|
|
|
task libsdsAndroid, "Build the mobile bindings for Android (uses ARCH env var)":
|
|
checkAndroidNdk()
|
|
let srcDir = "./library"
|
|
buildMobileAndroid srcDir, "-d:chronicles_log_level=ERROR"
|
|
|
|
task libsdsAndroidArm64, "Build Android arm64 bindings":
|
|
checkAndroidNdk()
|
|
putEnv("ARCH", "arm64")
|
|
buildMobileAndroid "./library", "-d:chronicles_log_level=ERROR"
|
|
|
|
task libsdsAndroidAmd64, "Build Android amd64 bindings":
|
|
checkAndroidNdk()
|
|
putEnv("ARCH", "amd64")
|
|
buildMobileAndroid "./library", "-d:chronicles_log_level=ERROR"
|
|
|
|
task libsdsAndroidX86, "Build Android x86 bindings":
|
|
checkAndroidNdk()
|
|
putEnv("ARCH", "i386")
|
|
buildMobileAndroid "./library", "-d:chronicles_log_level=ERROR"
|
|
|
|
task libsdsAndroidArm, "Build Android arm bindings":
|
|
checkAndroidNdk()
|
|
putEnv("ARCH", "arm")
|
|
buildMobileAndroid "./library", "-d:chronicles_log_level=ERROR"
|
|
|
|
task libsds, "Build the shared library for the current platform":
|
|
when defined(macosx):
|
|
exec "nimble libsdsDynamicMac"
|
|
elif defined(windows):
|
|
exec "nimble libsdsDynamicWindows"
|
|
else:
|
|
exec "nimble libsdsDynamicLinux"
|
|
|
|
task clean, "Remove build artifacts":
|
|
if dirExists "build":
|
|
rmDir "build"
|