diff --git a/recipes/tiledb/all/conandata.yml b/recipes/tiledb/all/conandata.yml new file mode 100644 index 0000000000000..9683a1cfcc4e0 --- /dev/null +++ b/recipes/tiledb/all/conandata.yml @@ -0,0 +1,4 @@ +sources: + "2.26.1": + url: "https://github.com/TileDB-Inc/TileDB/archive/refs/tags/2.26.1.tar.gz" + sha256: "f90461850c6f87f63fe77788d7932fd53a4d1de7e2ba7263f5e8f2fd1df23e38" diff --git a/recipes/tiledb/all/conanfile.py b/recipes/tiledb/all/conanfile.py new file mode 100644 index 0000000000000..3a434ad427fa5 --- /dev/null +++ b/recipes/tiledb/all/conanfile.py @@ -0,0 +1,275 @@ +import os + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build import check_min_cppstd, stdcpp_library +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import get, copy, rmdir, replace_in_file, save +from conan.tools.gnu import PkgConfigDeps +from conan.tools.scm import Version + +required_conan_version = ">=1.53.0" + +class TileDBConan(ConanFile): + name = "tiledb" + description = ("TileDB is a powerful engine for storing and accessing dense and sparse multi-dimensional arrays, " + "which can help you model any complex data efficiently.") + license = "MIT" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/TileDB-Inc/TileDB" + topics = ("data-science", "storage-engine", "s3", "sparse-data", "scientific-computing", "s3-storage", + "arrays", "data-analysis", "dataframes", "dense-data", "sparse-arrays") + + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + options = { + "shared": [True, False], + "fPIC": [True, False], + "cpp_api": [True, False], + "s3": [True, False], + "azure": [True, False], + "gcs": [True, False], + "serialization": [True, False], + "webp": [True, False], + "tools": [True, False], + "remove_deprecations": [True, False], + "verbose": [True, False], + "stats": [True, False], + "experimental_features": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + "cpp_api": True, + "s3": False, + "azure": False, + "gcs": False, + "serialization": False, + "webp": True, + "tools": False, + "remove_deprecations": False, + "verbose": False, + "stats": True, + "experimental_features": False, + } + options_description = { + "cpp_api": "Enable building of the TileDB C++ API", + "s3": "Support AWS S3 Storage", + "azure": "Support Azure Blob Storage", + "gcs": "Support Google Cloud Storage", + "serialization": "Enable TileDB Cloud support by building with support for query serialization.", + "webp": "Support WebP compression", + "tools": "Build tiledb command-line tool", + "remove_deprecations": "Do not build deprecated APIs", + "verbose": "Print TileDB errors with verbosity", + "stats": "Enable internal TileDB statistics gathering", + "experimental_features": "Build and include experimental features", + } + + @property + def _min_cppstd(self): + return 20 + + @property + def _compilers_minimum_version(self): + # https://github.com/TileDB-Inc/TileDB/blob/2.21.0/doc/dev/BUILD.md#prerequisites + return { + "gcc": "10", + "clang": "10", + "apple-clang": "14", + "msvc": "192", + "Visual Studio": "16", + } + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + self.options.rm_safe("fPIC") + if self.options.serialization: + self.options["libcurl"].with_zstd = True + if self.options.azure: + self.options["azure-sdk-for-cpp"]["azure-storage-blobs"] = True + if self.options.s3: + self.options["aws-sdk-cpp"].s3 = True + self.options["aws-sdk-cpp"]["identity-management"] = True + self.options["aws-sdk-cpp"].sts = True + + def layout(self): + cmake_layout(self, src_folder="src") + + def requirements(self): + # TileDB has no transitive header deps + self.requires("bzip2/1.0.8") + self.requires("libxml2/[>=2.12.5 <3]") + self.requires("lz4/1.9.4") + self.requires("spdlog/1.14.1") + self.requires("xz_utils/[>=5.4.5 <6]") + self.requires("zlib/[>=1.2.11 <2]") + self.requires("zstd/[^1.5]") + if self.settings.os != "Windows": + self.requires("openssl/[>=1.1 <4]") + self.requires("libmagic/5.45") + if self.options.azure: + self.requires("azure-sdk-for-cpp/1.11.3") + if self.options.gcs: + self.requires("google-cloud-cpp/2.28.0") + if self.options.serialization: + self.requires("capnproto/1.0.2") + self.requires("libcurl/[>=7.78 <9]") + if self.options.s3: + self.requires("aws-sdk-cpp/1.11.352") + if self.options.tools: + self.requires("clipp/1.2.3") + if self.options.webp: + self.requires("libwebp/1.4.0") + + # TODO: unvendor + # - bitshuffle + # - blosc + # - boost::interprocess + # - nlohmann_json + # - tcb-span + + def validate(self): + if self.settings.compiler.cppstd: + check_min_cppstd(self, self._min_cppstd) + minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False) + if minimum_version and Version(self.settings.compiler.version) < minimum_version: + raise ConanInvalidConfiguration( + f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support." + ) + + if self.options.serialization and not self.dependencies["libcurl"].options.with_zstd: + raise ConanInvalidConfiguration("TileDB serialization requires libcurl with with_zstd option enabled.") + if self.options.s3: + aws_opts = self.dependencies["aws-sdk-cpp"].options + if not (aws_opts.get_safe("s3") and aws_opts.get_safe("identity-management") and aws_opts.get_safe("sts")): + raise ConanInvalidConfiguration( + f"TileDB S3 support requires aws-sdk-cpp with 's3', 'identity-management' and 'sts' options enabled." + ) + + def build_requirements(self): + self.tool_requires("cmake/[>=3.21 <4]") + if not self.conf.get("tools.gnu:pkg_config", default=False, check_type=str): + self.tool_requires("pkgconf/[>=2.2 <3]") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + tc = CMakeToolchain(self) + # https://github.com/TileDB-Inc/TileDB/blob/2.26.1/cmake/Options/BuildOptions.cmake + tc.cache_variables["BUILD_SHARED_LIBS"] = self.options.shared + tc.cache_variables["TILEDB_AZURE"] = self.options.azure + tc.cache_variables["TILEDB_CPP_API"] = self.options.cpp_api + tc.cache_variables["TILEDB_DISABLE_AUTO_VCPKG"] = True + tc.cache_variables["TILEDB_EXPERIMENTAL_FEATURES"] = self.options.experimental_features + tc.cache_variables["TILEDB_GCS"] = self.options.gcs + tc.cache_variables["TILEDB_INSTALL_LIBDIR"] = os.path.join(self.package_folder, "lib") + tc.cache_variables["TILEDB_REMOVE_DEPRECATIONS"] = self.options.remove_deprecations + tc.cache_variables["TILEDB_S3"] = self.options.s3 + tc.cache_variables["TILEDB_SERIALIZATION"] = self.options.serialization + tc.cache_variables["TILEDB_STATS"] = self.options.stats + tc.cache_variables["TILEDB_TESTS"] = False + tc.cache_variables["TILEDB_TOOLS"] = self.options.tools + tc.cache_variables["TILEDB_VERBOSE"] = self.options.verbose + tc.cache_variables["TILEDB_WEBP"] = self.options.webp + tc.cache_variables["TILEDB_WERROR"] = False + # Disable ExternalProject just in case + tc.cache_variables["FETCHCONTENT_FULLY_DISCONNECTED"] = True + tc.cache_variables["libmagic_DICTIONARY"] = os.path.join(self.dependencies["libmagic"].package_folder, "res", "magic.mgc").replace("\\", "/") + tc.generate() + + deps = CMakeDeps(self) + conan_to_cmake_name = { + "aws-sdk-cpp": "AWSSDK", + "azure-sdk-for-cpp": "azure-storage-blobs-cpp", + "bzip2": "BZip2", + "capnproto": "CapnProto", + "clipp": "clipp", + "google-cloud-cpp": "google_cloud_cpp_storage", + "libcurl": "CURL", + "libmagic": "unofficial-libmagic", + "libwebp": "WebP", + "libxml2": "LibXml2", + "lz4": "lz4", + "openssl": "OpenSSL", + "spdlog": "spdlog", + "zlib": "ZLIB", + "zstd": "zstd", + } + for conan_name, cmake_name in conan_to_cmake_name.items(): + deps.set_property(conan_name, "cmake_file_name", cmake_name) + + renamed_targets = { + "azure-sdk-for-cpp::azure-storage-blobs": "Azure::azure-storage-blobs", + "bzip2": "BZip2::BZip2", + "clipp": "clipp::clipp", + "google-cloud-cpp::storage": "google-cloud-cpp::storage", + "libmagic": "unofficial::libmagic::libmagic", + "libwebp::webp": "WebP::webp", + "libwebp::webpdecoder": "WebP::webpdecoder", + "libwebp::webpdemux": "WebP::webpdemux", + "libwebp::webpmux": "WebP::libwebpmux", + "lz4": "LZ4::LZ4", + "zlib": "ZLIB::ZLIB", + "zstd": "Zstd::Zstd", + } + for component, new_target_name in renamed_targets.items(): + deps.set_property(component, "cmake_target_name", new_target_name) + + deps.generate() + + deps = PkgConfigDeps(self) + deps.generate() + + def _patch_sources(self): + # Disable examples + replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"), + "add_subdirectory(examples)", "") + replace_in_file(self, os.path.join(self.source_folder, "CMakeLists.txt"), + "add_subdirectory(experimental/experimental_examples)", "") + # Don't actually run vcpkg + save(self, os.path.join(self.source_folder, "cmake", "Options", "TileDBToolchain.cmake"), "") + # No such target defined in CCI + if self.options.serialization: + capnproto_bindir = self.dependencies['capnproto'].cpp_info.bindir + replace_in_file(self, os.path.join(self.source_folder, "tiledb", "CMakeLists.txt"), + "set(CAPNP_PLUGIN_DIR $)", + f'set(CAPNP_PLUGIN_DIR "{capnproto_bindir}")') + + def build(self): + self._patch_sources() + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses")) + cmake = CMake(self) + cmake.install() + # tools are not installed by CMake + if self.options.tools: + suffix = ".exe" if self.settings.os == "Windows" else "" + copy(self, f"tiledb{suffix}", + src=os.path.join(self.build_folder, "tools"), + dst=os.path.join(self.package_folder, "bin"), + keep_path=False) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "lib", "cmake")) + + def package_info(self): + self.cpp_info.set_property("cmake_file_name", "TileDB") + suffix = "shared" if self.options.shared else "static" + self.cpp_info.set_property("cmake_target_name", f"TileDB::tiledb_{suffix}") + self.cpp_info.set_property("cmake_target_aliases", ["TileDB::tiledb"]) + self.cpp_info.set_property("pkg_config_name", "tiledb") + + self.cpp_info.libs = ["tiledb"] + if self.settings.os in ["Linux", "FreeBSD"]: + self.cpp_info.system_libs.extend(["m", "pthread", "dl"]) + if stdcpp_library(self): + self.cpp_info.system_libs.append(stdcpp_library(self)) diff --git a/recipes/tiledb/all/test_package/CMakeLists.txt b/recipes/tiledb/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..6de1a132987e0 --- /dev/null +++ b/recipes/tiledb/all/test_package/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.15) +project(test_package CXX C) + +find_package(TileDB REQUIRED CONFIG) + +if (TILEDB_CPP_API) + add_executable(${PROJECT_NAME}_cpp test_package.cpp) + target_link_libraries(${PROJECT_NAME}_cpp PRIVATE TileDB::tiledb) + target_compile_features(${PROJECT_NAME}_cpp PRIVATE cxx_std_17) +endif() + +add_executable(${PROJECT_NAME}_c test_package.c) +target_link_libraries(${PROJECT_NAME}_c PRIVATE TileDB::tiledb) +target_compile_features(${PROJECT_NAME}_c PRIVATE c_std_99) diff --git a/recipes/tiledb/all/test_package/conanfile.py b/recipes/tiledb/all/test_package/conanfile.py new file mode 100644 index 0000000000000..e12ef4e9a27cb --- /dev/null +++ b/recipes/tiledb/all/test_package/conanfile.py @@ -0,0 +1,42 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import cmake_layout, CMake, CMakeToolchain +from conan.tools.files import save, load + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str, run=True) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.variables["TILEDB_CPP_API"] = self.dependencies["tiledb"].options.cpp_api + tc.generate() + save(self, os.path.join(self.build_folder, "have_tools"), str(self.dependencies["tiledb"].options.tools)) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindir, "test_package_cpp") + if os.path.exists(bin_path): + self.run(bin_path, env="conanrun") + + bin_path = os.path.join(self.cpp.build.bindir, "test_package_c") + self.run(bin_path, env="conanrun") + + have_tools = load(self, os.path.join(self.build_folder, "have_tools")) == "True" + if have_tools: + self.run("tiledb help info", env="conanrun") diff --git a/recipes/tiledb/all/test_package/test_package.c b/recipes/tiledb/all/test_package/test_package.c new file mode 100644 index 0000000000000..399f427b0fe86 --- /dev/null +++ b/recipes/tiledb/all/test_package/test_package.c @@ -0,0 +1,15 @@ +#include + +#include + +int main() { + tiledb_ctx_t* ctx; + tiledb_ctx_alloc(NULL, &ctx); + tiledb_ctx_free(&ctx); + + int32_t major, minor, rev; + tiledb_version(&major, &minor, &rev); + printf("TileDB version: %d.%d.%d\n", major, minor, rev); + + return 0; +} diff --git a/recipes/tiledb/all/test_package/test_package.cpp b/recipes/tiledb/all/test_package/test_package.cpp new file mode 100644 index 0000000000000..a8b39dd993dc1 --- /dev/null +++ b/recipes/tiledb/all/test_package/test_package.cpp @@ -0,0 +1,14 @@ +#include + +#include + +int main() { + tiledb::Context ctx; + + auto version = tiledb::version(); + std::cout << "TileDB version: " + << std::get<0>(version) << "." << std::get<1>(version) << "." << std::get<2>(version) + << std::endl; + + return 0; +} diff --git a/recipes/tiledb/config.yml b/recipes/tiledb/config.yml new file mode 100644 index 0000000000000..a6f63ba7f5ece --- /dev/null +++ b/recipes/tiledb/config.yml @@ -0,0 +1,3 @@ +versions: + "2.26.1": + folder: all