253 lines
9.5 KiB
Python
253 lines
9.5 KiB
Python
import re
|
|
import shutil
|
|
import subprocess
|
|
|
|
from conan import ConanFile
|
|
from conan.tools.build import check_min_cppstd, cross_building
|
|
from conan.tools.layout import basic_layout
|
|
|
|
|
|
# type: ignore[assignment,attr-defined,import-error]
|
|
|
|
|
|
def _parse_version_tuple(text: str):
|
|
match = re.search(r"(\d+)\.(\d+)(?:\.(\d+))?", text)
|
|
if not match:
|
|
return None
|
|
major = int(match.group(1))
|
|
minor = int(match.group(2))
|
|
patch = int(match.group(3) or "0")
|
|
return (major, minor, patch)
|
|
|
|
|
|
def _tool_on_path_satisfies(name: str, minimum: tuple[int, int, int]) -> bool:
|
|
tool_path = shutil.which(name)
|
|
if not tool_path:
|
|
return False
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
[tool_path, "--version"],
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
except (OSError, subprocess.SubprocessError):
|
|
return False
|
|
|
|
version_text = (result.stdout or result.stderr or "").strip()
|
|
version = _parse_version_tuple(version_text)
|
|
if version is None:
|
|
return False
|
|
|
|
return minimum <= version < (2, 0, 0)
|
|
|
|
|
|
class YamsConan(ConanFile):
|
|
name = "yams"
|
|
version = "0.20.5" # x-release-please-version
|
|
license = "GPL-3.0-or-later"
|
|
author = "YAMS Contributors"
|
|
url = "https://github.com/trvon/yams"
|
|
description = "Yet Another Memory System - Persistent memory for LLMs"
|
|
topics = ("storage", "content-addressed", "deduplication", "search")
|
|
|
|
settings = "os", "compiler", "build_type", "arch"
|
|
options = {
|
|
"build_tests": [True, False],
|
|
"build_benchmarks": [True, False],
|
|
"enable_profiling": [True, False],
|
|
"enable_onnx": [True, False],
|
|
"enable_re2": [True, False],
|
|
}
|
|
default_options = {
|
|
"build_tests": False,
|
|
"build_benchmarks": False,
|
|
"enable_profiling": False,
|
|
"enable_onnx": False, # deprecated; opt in with setup.sh --with-onnx
|
|
"enable_re2": True,
|
|
}
|
|
|
|
generators = ("MesonToolchain", "PkgConfigDeps", "CMakeDeps")
|
|
|
|
def requirements(self):
|
|
# Core dependencies
|
|
self.requires("spdlog/1.13.0")
|
|
self.requires("cli11/2.4.1")
|
|
self.requires("nlohmann_json/3.11.3")
|
|
# Force sqlite3 build from source with FTS5 enabled
|
|
self.requires(
|
|
"sqlite3/3.44.2",
|
|
options={
|
|
"enable_fts5": True,
|
|
"enable_json1": True,
|
|
"enable_rtree": True,
|
|
"omit_load_extension": False,
|
|
},
|
|
force=True, # Force rebuild with our options
|
|
)
|
|
self.requires("zlib/1.3.1")
|
|
self.requires("zstd/1.5.5")
|
|
if self.settings.os not in ["iOS", "Android"]: # type: ignore
|
|
self.requires("libarchive/3.7.6")
|
|
self.requires("openssl/3.2.0")
|
|
self.requires("libcurl/8.10.1")
|
|
self.requires("protobuf/3.21.12")
|
|
if self.settings.os not in ["iOS", "Android"]: # type: ignore
|
|
self.requires("taglib/2.0")
|
|
self.requires("tl-expected/1.1.0")
|
|
self.requires("boost/1.85.0")
|
|
|
|
if self.options.build_tests: # type: ignore
|
|
# Catch2 must be a regular requirement so Meson dependency()
|
|
# can resolve catch2/catch2-with-main via generated deps.
|
|
self.requires("catch2/3.5.2")
|
|
|
|
# ONNX Runtime for vector/embedding support (optional)
|
|
if self.options.enable_onnx: # type: ignore
|
|
# Keep in sync with conan/onnxruntime recipe.
|
|
# DirectML NuGet releases can lag behind GitHub releases.
|
|
self.requires("onnxruntime/1.23.0")
|
|
# Set compiler flags for clang 19
|
|
if self.settings.compiler != "msvc":
|
|
self.conf.append("tools.build:cxxflags", "-Wno-unused-but-set-variable")
|
|
self.conf.append("tools.build:cxxflags", "-Wno-unused-function")
|
|
self.conf.append("tools.build:cxxflags", "-Wno-deprecated-declarations")
|
|
# Windows uses the packaged ONNX Runtime binaries directly and does
|
|
# not need the extra oneTBB/hwloc graph that breaks local MSVC 195
|
|
# builds in Conan Center's hwloc recipe.
|
|
if self.settings.os != "Windows": # type: ignore
|
|
try:
|
|
self.requires("onetbb/2021.12.0")
|
|
except Exception:
|
|
pass
|
|
|
|
self.requires("xz_utils/5.8.3")
|
|
|
|
# RE2 regex engine for high-performance grep (optional)
|
|
if self.options.enable_re2: # type: ignore
|
|
self.requires("re2/20251105")
|
|
|
|
def build_requirements(self):
|
|
self.tool_requires("pkgconf/2.1.0")
|
|
if _tool_on_path_satisfies("meson", (1, 2, 2)):
|
|
self.output.info("Using Meson from PATH; skipping Conan Meson tool_requires")
|
|
else:
|
|
self.tool_requires("meson/[>=1.2.2 <2]")
|
|
|
|
if _tool_on_path_satisfies("ninja", (1, 10, 2)):
|
|
self.output.info("Using Ninja from PATH; skipping Conan Ninja tool_requires")
|
|
else:
|
|
self.tool_requires("ninja/[>=1.10.2 <2]")
|
|
|
|
if cross_building(self):
|
|
# Cross-builds still need a build-machine protoc for Meson codegen.
|
|
self.tool_requires("protobuf/3.21.12")
|
|
|
|
if self.options.build_benchmarks: # type: ignore
|
|
self.requires("benchmark/1.8.3")
|
|
if self.options.enable_profiling: # type: ignore
|
|
self.requires("tracy/0.13.1")
|
|
|
|
def configure(self):
|
|
# Force new C++11 ABI on Linux (Ubuntu 24.04+ compatibility)
|
|
if self.settings.os == "Linux": # type: ignore
|
|
if self.settings.compiler in ["gcc", "clang"]: # type: ignore
|
|
self.settings.compiler.libcxx = "libstdc++11" # type: ignore
|
|
|
|
# Force SQLite3 to build from source with FTS5 (don't use pre-built binaries)
|
|
self.options["sqlite3"].enable_fts5 = True # type: ignore
|
|
self.options["sqlite3"].enable_json1 = True # type: ignore
|
|
self.options["sqlite3"].enable_rtree = True # type: ignore
|
|
self.options["sqlite3"].omit_load_extension = False # type: ignore
|
|
self.options["libcurl"].with_ssl = "openssl"
|
|
self.options["libcurl"].with_zlib = True
|
|
self.options["libcurl"].shared = False
|
|
self.options["openssl"].shared = False
|
|
try:
|
|
self.options["libarchive"].shared = False
|
|
self.options[
|
|
"libarchive"
|
|
].with_acl = False # Avoid libacl link issues on Linux CI
|
|
except Exception:
|
|
pass
|
|
try:
|
|
self.options["taglib"].shared = False
|
|
except Exception:
|
|
pass
|
|
self.options["spdlog"].header_only = False
|
|
|
|
if self.settings.os in ["iOS", "Android"]: # type: ignore
|
|
# Mobile cross-builds do not benefit from a compiled fmt library and
|
|
# currently hit simulator-specific toolchain failures in fmt's
|
|
# source build path. Header-only fmt keeps the dependency surface
|
|
# smaller and avoids that compiler path entirely.
|
|
self.options["fmt"].header_only = True # type: ignore
|
|
# Mobile builds also do not need a separately compiled spdlog
|
|
# library. Keeping it header-only avoids Apple SDK-specific
|
|
# failures in spdlog's bundled/external fmt compile path.
|
|
self.options["spdlog"].header_only = True # type: ignore
|
|
|
|
# YAMS uses Boost.Asio (header-only) plus the linked system/thread
|
|
# modules on every platform. Disable the unrelated compiled Boost
|
|
# libraries everywhere: desktop builds no longer compile ~20 unused
|
|
# components, and mobile cross-builds avoid platform-specific ones like
|
|
# boost.context assembly or locale/iconv stacks.
|
|
for boost_opt in (
|
|
"without_cobalt",
|
|
"without_context",
|
|
"without_contract",
|
|
"without_coroutine",
|
|
"without_fiber",
|
|
"without_graph",
|
|
"without_iostreams",
|
|
"without_json",
|
|
"without_locale",
|
|
"without_log",
|
|
"without_math",
|
|
"without_nowide",
|
|
"without_program_options",
|
|
"without_random",
|
|
"without_regex",
|
|
"without_serialization",
|
|
"without_stacktrace",
|
|
"without_test",
|
|
"without_type_erasure",
|
|
"without_url",
|
|
"without_wave",
|
|
):
|
|
setattr(self.options["boost"], boost_opt, True) # type: ignore
|
|
|
|
if self.options.enable_onnx: # type: ignore
|
|
self.options["onnxruntime"].fPIC = True
|
|
self.options["onnxruntime"].shared = True
|
|
if self.settings.os != "Windows": # type: ignore
|
|
# oneTBB requires hwloc with shared=True on non-Windows builds.
|
|
self.options["hwloc"].shared = True
|
|
|
|
def validate(self):
|
|
check_min_cppstd(self, "20")
|
|
|
|
def layout(self):
|
|
basic_layout(self)
|
|
|
|
def generate(self):
|
|
try:
|
|
from conan.tools.meson import MesonToolchain
|
|
from conan.tools.gnu import PkgConfigDeps
|
|
from conan.tools.cmake import CMakeDeps
|
|
from conan.tools.env import VirtualBuildEnv
|
|
|
|
VirtualBuildEnv(self).generate()
|
|
tc = MesonToolchain(self)
|
|
if (
|
|
self.settings.os == "Linux"
|
|
and self.settings.compiler.libcxx == "libstdc++11"
|
|
): # type: ignore
|
|
tc.preprocessor_definitions["_GLIBCXX_USE_CXX11_ABI"] = "1"
|
|
tc.generate()
|
|
|
|
PkgConfigDeps(self).generate()
|
|
CMakeDeps(self).generate()
|
|
except Exception:
|
|
pass
|