From e413122a422283ecc3b702c94a9eb4829b6faf1d Mon Sep 17 00:00:00 2001 From: Arnaud Date: Tue, 24 Feb 2026 20:57:59 +0400 Subject: [PATCH] Add nix files --- cli/CMakeLists.txt | 393 ++++++++++++++++++++++++++++++++++++++++++ cli/logos.cpp | 3 + cli/logos.h | 3 + cli/logos_manager.cpp | 67 +++++++ cli/logos_manager.h | 39 +++++ cli/main.cpp | 38 ++++ cli/metadata.json | 12 ++ flake.nix | 8 +- nix/cli.nix | 177 +++++++++++++++++++ 9 files changed, 739 insertions(+), 1 deletion(-) create mode 100644 cli/CMakeLists.txt create mode 100644 cli/logos.cpp create mode 100644 cli/logos.h create mode 100644 cli/logos_manager.cpp create mode 100644 cli/logos_manager.h create mode 100644 cli/main.cpp create mode 100644 cli/metadata.json create mode 100644 nix/cli.nix diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt new file mode 100644 index 0000000..a56445b --- /dev/null +++ b/cli/CMakeLists.txt @@ -0,0 +1,393 @@ +cmake_minimum_required(VERSION 3.16) +project(LogosStorageCLI LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +########### DEPENDENCIES ########### + +# This section locates the required dependencies in 3 different ways: +# 1- With NIX, the root folders (LOGOS_LIBLOGOS_ROOT, LOGOS_CPP_SDK_ROOT, +# and LOGOS_STORAGE_ROOT) are defined and point to the correct locations in +# the Nix store. +# 2- If the root folders are fetched from source (basically using git) in the +# parent folder, this is detected and used. +# 3- If none of the above apply, the vendor folders inside this project are used, +# meaning the dependencies need to be fetched using git submodules. + +if(NOT DEFINED LOGOS_LIBLOGOS_ROOT) + set(_parent_liblogos "${CMAKE_SOURCE_DIR}/../../logos-liblogos") + set(_use_vendor ${LOGOS_STORAGE_CLI_USE_VENDOR}) + if(NOT _use_vendor) + if(NOT EXISTS "${_parent_liblogos}/src/common/interface.h") + set(_use_vendor ON) + endif() + endif() + if(_use_vendor) + set(LOGOS_LIBLOGOS_ROOT "${CMAKE_SOURCE_DIR}/../vendor/logos-liblogos") + else() + set(LOGOS_LIBLOGOS_ROOT "${_parent_liblogos}") + endif() +endif() + +if(NOT DEFINED LOGOS_CPP_SDK_ROOT) + set(_parent_cpp_sdk "${CMAKE_SOURCE_DIR}/../../logos-cpp-sdk") + set(_use_vendor ${LOGOS_STORAGE_CLI_USE_VENDOR}) + if(NOT _use_vendor) + if(NOT EXISTS "${_parent_cpp_sdk}/cpp/logos_api.h") + set(_use_vendor ON) + endif() + endif() + if(_use_vendor) + set(LOGOS_CPP_SDK_ROOT "${CMAKE_SOURCE_DIR}/../vendor/logos-cpp-sdk") + else() + set(LOGOS_CPP_SDK_ROOT "${_parent_cpp_sdk}") + endif() +endif() + +if(NOT DEFINED LOGOS_STORAGE_ROOT) + set(_parent_storage_module "${CMAKE_SOURCE_DIR}/../../logos-storage-module") + set(_use_vendor ${LOGOS_STORAGE_CLI_USE_VENDOR}) + if(NOT _use_vendor) + if(NOT EXISTS "${_parent_storage_module}/storage_module_plugin.h") + set(_use_vendor ON) + endif() + endif() + if(_use_vendor) + set(LOGOS_STORAGE_ROOT "${CMAKE_SOURCE_DIR}/../vendor/logos-storage-module") + else() + set(LOGOS_STORAGE_ROOT "${_parent_storage_module}") + endif() +endif() + +set(_liblogos_found FALSE) +if(EXISTS "${LOGOS_LIBLOGOS_ROOT}/src/common/interface.h") + set(_liblogos_found TRUE) + set(_liblogos_is_source TRUE) +elseif(EXISTS "${LOGOS_LIBLOGOS_ROOT}/include/interface.h") + set(_liblogos_found TRUE) + set(_liblogos_is_source FALSE) +endif() + +set(_cpp_sdk_found FALSE) +if(EXISTS "${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h") + set(_cpp_sdk_found TRUE) + set(_cpp_sdk_is_source TRUE) +elseif(EXISTS "${LOGOS_CPP_SDK_ROOT}/include/cpp/logos_api.h") + set(_cpp_sdk_found TRUE) + set(_cpp_sdk_is_source FALSE) +endif() + +set(_storage_module_found FALSE) +if(EXISTS "${LOGOS_STORAGE_ROOT}/storage_module_plugin.h") + set(_storage_module_found TRUE) + set(_storage_module_is_source TRUE) +elseif(EXISTS "${LOGOS_STORAGE_ROOT}/include/storage_module_api.h") + set(_storage_module_found TRUE) + set(_storage_module_is_source FALSE) +endif() + +if(NOT _liblogos_found) + message(FATAL_ERROR "logos-liblogos not found at ${LOGOS_LIBLOGOS_ROOT}. " + "Set LOGOS_LIBLOGOS_ROOT or run git submodule update --init --recursive.") +endif() + +if(NOT _cpp_sdk_found) + message(FATAL_ERROR "logos-cpp-sdk not found at ${LOGOS_CPP_SDK_ROOT}. " + "Set LOGOS_CPP_SDK_ROOT or run git submodule update --init --recursive.") +endif() + +if(NOT _storage_module_found) + message(FATAL_ERROR "logos-storage-module not found at ${LOGOS_STORAGE_ROOT}. " + "Set LOGOS_STORAGE_ROOT or run git submodule update --init --recursive.") +endif() + +message(STATUS "Using logos-liblogos at: ${LOGOS_LIBLOGOS_ROOT}") +message(STATUS "Using logos-cpp-sdk at: ${LOGOS_CPP_SDK_ROOT}") +message(STATUS "Using logos-storage-module at: ${LOGOS_STORAGE_ROOT}") + +########### DEPENDENCIES END ########### + +########### SOURCES ########### + +set(SOURCES + main.cpp + logos_manager.cpp + logos_manager.h +) + +# Add SDK sources (only if source layout, installed layout uses the library) +if(_cpp_sdk_is_source) + list(APPEND SOURCES + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.h + ${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.h + ${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.h + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_types.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_types.h + ) +endif() + +########### SOURCES END ########### + +########### CPP GENERATOR ########### + +# Define metadata json path +set(METADATA_JSON "${CMAKE_CURRENT_SOURCE_DIR}/metadata.json") + +# Run the cpp generator for the storage module (produces storage_module_api.h/cpp). +# Only for source layout - nix builds already have pre-generated files. +if(_storage_module_is_source) + set(PLUGINS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated_code") + + set(CPP_GENERATOR_BUILD_DIR "${LOGOS_CPP_SDK_ROOT}/../build/cpp-generator") + set(CPP_GENERATOR "${CPP_GENERATOR_BUILD_DIR}/bin/logos-cpp-generator") + + if(NOT TARGET cpp_generator_build) + add_custom_target(cpp_generator_build + COMMAND bash "${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.." + COMMENT "Building logos-cpp-generator via ${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + VERBATIM + ) + endif() + + add_custom_target(run_build_storage_module + COMMAND "${CMAKE_COMMAND}" -S "${LOGOS_STORAGE_ROOT}" -B "${LOGOS_STORAGE_ROOT}/build" + COMMAND "${CMAKE_COMMAND}" --build "${LOGOS_STORAGE_ROOT}/build" --target all + WORKING_DIRECTORY "${LOGOS_STORAGE_ROOT}/.." + COMMENT "Building storage module in ${LOGOS_STORAGE_ROOT}/build" + VERBATIM + ) + + if(APPLE) + set(PLUGIN_FILE "${LOGOS_STORAGE_ROOT}/build/modules/storage_module_plugin.dylib") + elseif(UNIX) + set(PLUGIN_FILE "${LOGOS_STORAGE_ROOT}/build/modules/storage_module_plugin.so") + else() + message(FATAL_ERROR "storage_module_plugin is not found.") + endif() + + add_custom_target(run_cpp_generator_storage_module + COMMAND ${CMAKE_COMMAND} -E make_directory "${PLUGINS_OUTPUT_DIR}" + COMMAND "${CPP_GENERATOR}" "${PLUGIN_FILE}" --interface "${LOGOS_STORAGE_ROOT}/storage_module_interface.h" --module-only --output-dir "${PLUGINS_OUTPUT_DIR}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Running logos-cpp-generator on ${PLUGIN_FILE} with output-dir ${PLUGINS_OUTPUT_DIR}" + VERBATIM + ) + + add_dependencies(run_cpp_generator_storage_module cpp_generator_build) + add_dependencies(run_cpp_generator_storage_module run_build_storage_module) +endif() + +# Generate logos_sdk.cpp via --general-only --metadata. +# This file #includes all module APIs (storage_module_api.cpp etc.) based on +# the dependencies declared in metadata.json. +# storage_module_api.cpp is NOT added directly to SOURCES to avoid AUTOMOC issues +# with files that don't exist at configure time. +if(_cpp_sdk_is_source) + if(NOT DEFINED PLUGINS_OUTPUT_DIR) + set(PLUGINS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated_code") + endif() + + if(NOT DEFINED CPP_GENERATOR_BUILD_DIR) + set(CPP_GENERATOR_BUILD_DIR "${LOGOS_CPP_SDK_ROOT}/../build/cpp-generator") + endif() + + if(NOT DEFINED CPP_GENERATOR) + set(CPP_GENERATOR "${CPP_GENERATOR_BUILD_DIR}/bin/logos-cpp-generator") + endif() + + if(NOT TARGET cpp_generator_build) + add_custom_target(cpp_generator_build + COMMAND bash "${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.." + COMMENT "Building logos-cpp-generator via ${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh" + VERBATIM + ) + endif() + + add_custom_command( + OUTPUT "${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp" + COMMAND ${CMAKE_COMMAND} -E make_directory "${PLUGINS_OUTPUT_DIR}" + COMMAND "${CPP_GENERATOR}" --metadata "${METADATA_JSON}" --general-only --output-dir "${PLUGINS_OUTPUT_DIR}" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.." + DEPENDS "${METADATA_JSON}" cpp_generator_build + VERBATIM + ) + + add_custom_target(run_cpp_generator_logos_cli DEPENDS "${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp") + + if(_storage_module_is_source) + add_dependencies(run_cpp_generator_logos_cli run_cpp_generator_storage_module) + endif() + + list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp) + + # Mark as generated so CMake knows to wait for it + set_source_files_properties( + ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp + PROPERTIES GENERATED TRUE + ) +else() + # For installed/nix layout, logos_sdk.cpp is already pre-generated + set(PLUGINS_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/generated_code") + list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp) +endif() + +########### CPP GENERATOR END ########### + +########### APP DEFINITION ########### + +# Find Qt packages +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core RemoteObjects) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core RemoteObjects) + +# Link directories +link_directories( + ${LOGOS_LIBLOGOS_ROOT}/lib + ${LOGOS_CPP_SDK_ROOT}/lib +) + +# Set output directories +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +# Create the executable +add_executable(logos-storage-cli ${SOURCES}) + +# Link libraries +target_link_libraries(logos-storage-cli PRIVATE + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::RemoteObjects + logos_core +) + +# Link SDK library if using installed layout (source layout compiles the SDK directly) +if(NOT _cpp_sdk_is_source) + find_library(LOGOS_SDK_LIB logos_sdk PATHS ${LOGOS_CPP_SDK_ROOT}/lib NO_DEFAULT_PATH REQUIRED) + target_link_libraries(logos-storage-cli PRIVATE ${LOGOS_SDK_LIB}) +endif() + +########### APP DEFINITION END ########### + +########### HEADERS ########### + +# Include directories +target_include_directories(logos-storage-cli PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${PLUGINS_OUTPUT_DIR} +) + +if(_liblogos_is_source) + target_include_directories(logos-storage-cli PRIVATE ${LOGOS_LIBLOGOS_ROOT}) +else() + target_include_directories(logos-storage-cli PRIVATE ${LOGOS_LIBLOGOS_ROOT}/include) +endif() + +if(_cpp_sdk_is_source) + target_include_directories(logos-storage-cli PRIVATE + ${LOGOS_CPP_SDK_ROOT}/cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/generated + ) +else() + target_include_directories(logos-storage-cli PRIVATE + ${LOGOS_CPP_SDK_ROOT}/include + ${LOGOS_CPP_SDK_ROOT}/include/cpp + ${LOGOS_CPP_SDK_ROOT}/include/core + ${PLUGINS_OUTPUT_DIR}/include + ) +endif() + +########### HEADERS END ########### + +########### GENERATOR DEPENDENCY ########### + +if(_cpp_sdk_is_source) + add_dependencies(logos-storage-cli run_cpp_generator_logos_cli) +endif() + +if(_storage_module_is_source) + add_dependencies(logos-storage-cli run_cpp_generator_storage_module) +endif() + +########### GENERATOR DEPENDENCY END ########### + +########### LOGOS DEPENDENCIES LIBRARIES ########### + +# Check if logos_sdk library exists +if(NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.a" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.dylib" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.so") + set(LOGOS_CPP_SDK_BUILD_DIR "${LOGOS_CPP_SDK_ROOT}/build") + + add_custom_target(run_build_cpp_sdk + COMMAND ${CMAKE_COMMAND} -E make_directory "${LOGOS_CPP_SDK_BUILD_DIR}" + COMMAND ${CMAKE_COMMAND} -E chdir "${LOGOS_CPP_SDK_BUILD_DIR}" cmake ../cpp -GNinja -DCMAKE_POSITION_INDEPENDENT_CODE=ON + COMMAND ${CMAKE_COMMAND} -E chdir "${LOGOS_CPP_SDK_BUILD_DIR}" ninja + COMMAND ${CMAKE_COMMAND} -E make_directory "${LOGOS_CPP_SDK_ROOT}/lib" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${LOGOS_CPP_SDK_BUILD_DIR}/lib/liblogos_sdk.a" + "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.a" + WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}" + COMMENT "Build cpp sdk and copy liblogos_sdk.a to ${LOGOS_CPP_SDK_ROOT}/lib" + VERBATIM + ) + + add_dependencies(logos-storage-cli run_build_cpp_sdk) +endif() + +if(NOT EXISTS "${LOGOS_LIBLOGOS_ROOT}/lib/liblogos_core.a" AND NOT EXISTS "${LOGOS_LIBLOGOS_ROOT}/lib/liblogos_core.dylib" AND NOT EXISTS "${LOGOS_LIBLOGOS_ROOT}/lib/liblogos_core.so") + set(LOGOS_LIBLOGOS_BUILD_DIR "${LOGOS_LIBLOGOS_ROOT}/build") + + add_custom_target(run_build_liblogos + COMMAND ${CMAKE_COMMAND} -E make_directory "${LOGOS_LIBLOGOS_BUILD_DIR}" + COMMAND ${CMAKE_COMMAND} -E chdir "${LOGOS_LIBLOGOS_BUILD_DIR}" cmake .. -GNinja -DCMAKE_POSITION_INDEPENDENT_CODE=ON + COMMAND ${CMAKE_COMMAND} -E chdir "${LOGOS_LIBLOGOS_BUILD_DIR}" ninja + COMMAND ${CMAKE_COMMAND} -E make_directory "${LOGOS_LIBLOGOS_ROOT}/lib" + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${LOGOS_LIBLOGOS_BUILD_DIR}/lib" + "${LOGOS_LIBLOGOS_ROOT}/lib" + WORKING_DIRECTORY "${LOGOS_LIBLOGOS_ROOT}" + COMMENT "Build logos-liblogos and copy liblogos_core.a to ${LOGOS_LIBLOGOS_ROOT}/lib" + VERBATIM + ) + + add_dependencies(logos-storage-cli run_build_liblogos) +endif() + +########### LOGOS DEPENDENCIES END ########### + +########### RUNTIME LINKS ########### + +# Set RPATH settings for the executable +if(APPLE) + set_target_properties(logos-storage-cli PROPERTIES + INSTALL_RPATH "@executable_path/../lib" + BUILD_WITH_INSTALL_RPATH TRUE + ) +elseif(UNIX) + set_target_properties(logos-storage-cli PROPERTIES + INSTALL_RPATH "$ORIGIN/../lib" + BUILD_WITH_INSTALL_RPATH TRUE + ) +endif() + +########### RUNTIME LINKS END ########### + +########### INSTALL ########### + +# Install rules +install(TARGETS logos-storage-cli + RUNTIME DESTINATION bin +) + +########### INSTALL END ########### diff --git a/cli/logos.cpp b/cli/logos.cpp new file mode 100644 index 0000000..b643a9c --- /dev/null +++ b/cli/logos.cpp @@ -0,0 +1,3 @@ +// This file is intentionally empty. +// The Logos lifecycle manager implementation has been moved to logos_manager.cpp +// to avoid conflict with the logos.h header generated by logos-liblogos. diff --git a/cli/logos.h b/cli/logos.h new file mode 100644 index 0000000..1d2f80b --- /dev/null +++ b/cli/logos.h @@ -0,0 +1,3 @@ +// This file is intentionally empty. +// The Logos lifecycle manager has been moved to logos_manager.h +// to avoid conflict with the logos.h header generated by logos-liblogos. diff --git a/cli/logos_manager.cpp b/cli/logos_manager.cpp new file mode 100644 index 0000000..ad26210 --- /dev/null +++ b/cli/logos_manager.cpp @@ -0,0 +1,67 @@ +#include "logos_manager.h" + +#include +#include + +extern "C" { +void logos_core_set_plugins_dir(const char* plugins_dir); +void logos_core_start(); +void logos_core_cleanup(); +char** logos_core_get_loaded_plugins(); +int logos_core_load_plugin(const char* plugin_name); +} + +Logos::Logos(const QString& pluginsDir) + : m_pluginsDir(pluginsDir) +{} + +Logos::~Logos() +{ + if (m_initialized) { + cleanup(); + } +} + +bool Logos::init() +{ + std::cout << "Setting plugins directory to: " << m_pluginsDir.toStdString() << std::endl; + logos_core_set_plugins_dir(m_pluginsDir.toUtf8().constData()); + + logos_core_start(); + std::cout << "Logos Core started successfully!" << std::endl; + + if (!logos_core_load_plugin("capability_module")) { + std::cerr << "Failed to load capability_module plugin" << std::endl; + return false; + } + std::cout << "Successfully loaded capability_module plugin" << std::endl; + + if (!logos_core_load_plugin("storage_module")) { + std::cerr << "Failed to load storage_module plugin" << std::endl; + return false; + } + std::cout << "Successfully loaded storage_module plugin" << std::endl; + + m_api = std::make_unique("cli"); + m_initialized = true; + return true; +} + +void Logos::cleanup() +{ + if (!m_initialized) { + return; + } + + qDebug() << "Logos: cleanup..."; + + m_api.reset(); + logos_core_cleanup(); + + m_initialized = false; +} + +LogosAPI* Logos::api() const +{ + return m_api.get(); +} diff --git a/cli/logos_manager.h b/cli/logos_manager.h new file mode 100644 index 0000000..8aacb73 --- /dev/null +++ b/cli/logos_manager.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include "logos_api.h" + +// Logos manages the lifecycle of the Logos Core and its plugins. +// It handles initialization and cleanup of the Logos SDK. +// +// Usage: +// Logos logos(pluginsDir); +// if (!logos.init()) { return 1; } +// +// StorageModule storage(logos.api()); +// LogosResult result = storage.version(); +// +// // cleanup() is called automatically in destructor +class Logos { +public: + explicit Logos(const QString& pluginsDir); + ~Logos(); + + // Initialize the Logos Core: set plugins directory, start, and load required plugins. + // Returns true on success. + bool init(); + + // Cleanup the Logos Core. Called automatically in destructor. + void cleanup(); + + // Access to the LogosAPI instance for use with module APIs (e.g. StorageModule). + // Returns nullptr if init() has not been called successfully. + LogosAPI* api() const; + +private: + QString m_pluginsDir; + bool m_initialized = false; + std::unique_ptr m_api; +}; diff --git a/cli/main.cpp b/cli/main.cpp new file mode 100644 index 0000000..d764f2f --- /dev/null +++ b/cli/main.cpp @@ -0,0 +1,38 @@ +#include "logos_manager.h" + +#include +#include +#include + +#include "storage_module_api.h" + +int main(int argc, char* argv[]) { + QCoreApplication app(argc, argv); + + QCoreApplication::setOrganizationName("Logos"); + QCoreApplication::setApplicationName("LogosStorageCLI"); + + // Set the plugins directory + QString pluginsDir = QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../modules"); + + // Initialize Logos Core and load required plugins + Logos logos(pluginsDir); + if (!logos.init()) { + std::cerr << "Failed to initialize Logos" << std::endl; + return 1; + } + + // Use the Storage Module + StorageModule storage(logos.api()); + + // Echo: get version (does not require the node to be started) + LogosResult result = storage.version(); + if (result.success) { + std::cout << "Storage version: " << result.getString().toStdString() << std::endl; + } else { + std::cerr << "Failed to get storage version: " << result.getError().toStdString() << std::endl; + } + + // logos destructor calls cleanup() automatically + return 0; +} diff --git a/cli/metadata.json b/cli/metadata.json new file mode 100644 index 0000000..6292a13 --- /dev/null +++ b/cli/metadata.json @@ -0,0 +1,12 @@ +{ + "name": "logos_storage_cli", + "version": "1.0.0", + "description": "CLI workshop application for Logos Storage", + "author": "Logos Core Team", + "type": "cli", + "main": "logos-storage-cli", + "dependencies": [ + "storage_module" + ], + "capabilities": [] +} diff --git a/flake.nix b/flake.nix index c776664..b7523a7 100644 --- a/flake.nix +++ b/flake.nix @@ -48,12 +48,18 @@ logosStorageUI = lib; }; + # CLI package + cli = import ./nix/cli.nix { + inherit pkgs common src logosLiblogos logosSdk logosStorageModule logosCapabilityModule; + }; + in { # Individual outputs lib = lib; app = app; - + cli = cli; + # Default package default = app; } diff --git a/nix/cli.nix b/nix/cli.nix new file mode 100644 index 0000000..9c5d75b --- /dev/null +++ b/nix/cli.nix @@ -0,0 +1,177 @@ +# Builds the logos-storage-cli standalone CLI application +{ pkgs, common, src, logosLiblogos, logosSdk, logosStorageModule, logosCapabilityModule }: + +pkgs.stdenv.mkDerivation rec { + pname = "${common.pname}-cli"; + version = common.version; + + inherit src; + + # CLI has no design system or QML dependency: trim buildInputs accordingly + buildInputs = [ + pkgs.qt6.qtbase + pkgs.qt6.qtremoteobjects + pkgs.zstd + pkgs.krb5 + pkgs.abseil-cpp + ]; + + # Add logosSdk to nativeBuildInputs for logos-cpp-generator + nativeBuildInputs = common.nativeBuildInputs ++ [ logosSdk pkgs.patchelf ]; + + inherit (common) meta; + + # CLI is not a GUI application: still wrap so Qt shared libs are on LD_LIBRARY_PATH + dontWrapQtApps = false; + dontStrip = true; + + qtLibPath = pkgs.lib.makeLibraryPath ( + [ + pkgs.qt6.qtbase + pkgs.qt6.qtremoteobjects + pkgs.zstd + pkgs.krb5 + pkgs.zlib + pkgs.glib + pkgs.stdenv.cc.cc + ] + ); + + qtWrapperArgs = [ + "--prefix" "LD_LIBRARY_PATH" ":" qtLibPath + ]; + + preConfigure = '' + runHook prePreConfigure + + # Create generated_code directory for the CLI (cmake -S cli sets CMAKE_SOURCE_DIR=cli/) + mkdir -p ./cli/generated_code + + # Copy pre-generated API files from logos-storage-module + echo "Copying include files from logos-storage-module..." + if [ -d "${logosStorageModule}/include" ]; then + cp -r "${logosStorageModule}/include"/* ./cli/generated_code/ + echo "Copied include files:" + ls -la ./cli/generated_code/ + else + echo "Warning: No include directory found in logos-storage-module" + fi + + # Run logos-cpp-generator with cli/metadata.json and --general-only flag + # This generates logos_sdk.cpp which #includes storage_module_api.cpp + echo "Running logos-cpp-generator for CLI..." + logos-cpp-generator --metadata ${src}/cli/metadata.json --general-only --output-dir ./cli/generated_code + + echo "Checking generated files in cli/generated_code:" + ls -la ./cli/generated_code/ + + # Move generated headers to include/ subdirectory (installed layout convention) + if [ -f "./cli/generated_code/logos_sdk.h" ] || [ -f "./cli/generated_code/core_manager_api.h" ]; then + echo "Creating include directory and moving generated files..." + mkdir -p ./cli/generated_code/include + for file in ./cli/generated_code/*.h; do + [ -f "$file" ] && mv "$file" ./cli/generated_code/include/ + done + # Keep a copy of .cpp files in include/ so #include "storage_module_api.cpp" resolves + for file in ./cli/generated_code/*.cpp; do + [ -f "$file" ] && cp "$file" ./cli/generated_code/include/ + done + echo "Generated include directory:" + ls -la ./cli/generated_code/include/ + else + echo "Warning: No header files generated by logos-cpp-generator" + fi + + runHook postPreConfigure + ''; + + configurePhase = '' + runHook preConfigure + + echo "Configuring logos-storage-cli..." + echo "liblogos: ${logosLiblogos}" + echo "cpp-sdk: ${logosSdk}" + echo "storage-module: ${logosStorageModule}" + echo "capability-module: ${logosCapabilityModule}" + + test -d "${logosLiblogos}" || (echo "liblogos not found" && exit 1) + test -d "${logosSdk}" || (echo "cpp-sdk not found" && exit 1) + test -d "${logosStorageModule}" || (echo "storage-module not found" && exit 1) + test -d "${logosCapabilityModule}" || (echo "capability-module not found" && exit 1) + + cmake -S cli -B build/cli \ + -GNinja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=FALSE \ + -DCMAKE_INSTALL_RPATH="" \ + -DCMAKE_SKIP_BUILD_RPATH=TRUE \ + -DLOGOS_LIBLOGOS_ROOT=${logosLiblogos} \ + -DLOGOS_CPP_SDK_ROOT=${logosSdk} \ + -DLOGOS_STORAGE_ROOT=${logosStorageModule} + + runHook postConfigure + ''; + + buildPhase = '' + runHook preBuild + + cmake --build build/cli + echo "logos-storage-cli built successfully!" + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin $out/lib $out/modules + + # Install CLI binary + if [ -f "build/cli/bin/logos-storage-cli" ]; then + cp build/cli/bin/logos-storage-cli "$out/bin/" + echo "Installed logos-storage-cli binary" + fi + + # Copy the core binaries from liblogos + if [ -f "${logosLiblogos}/bin/logoscore" ]; then + cp -L "${logosLiblogos}/bin/logoscore" "$out/bin/" + echo "Installed logoscore binary" + fi + if [ -f "${logosLiblogos}/bin/logos_host" ]; then + cp -L "${logosLiblogos}/bin/logos_host" "$out/bin/" + echo "Installed logos_host binary" + fi + + # Copy required shared libraries from liblogos + if ls "${logosLiblogos}/lib/"liblogos_core.* >/dev/null 2>&1; then + cp -L "${logosLiblogos}/lib/"liblogos_core.* "$out/lib/" || true + fi + + # Copy SDK library if it exists + if ls "${logosSdk}/lib/"liblogos_sdk.* >/dev/null 2>&1; then + cp -L "${logosSdk}/lib/"liblogos_sdk.* "$out/lib/" || true + fi + + # Determine platform-specific plugin extension + OS_EXT="so" + case "$(uname -s)" in + Darwin) OS_EXT="dylib";; + Linux) OS_EXT="so";; + esac + + # Copy module plugins into the modules directory + if [ -f "${logosCapabilityModule}/lib/capability_module_plugin.$OS_EXT" ]; then + cp -L "${logosCapabilityModule}/lib/capability_module_plugin.$OS_EXT" "$out/modules/" + fi + if [ -f "${logosStorageModule}/lib/storage_module_plugin.$OS_EXT" ]; then + cp -L "${logosStorageModule}/lib/storage_module_plugin.$OS_EXT" "$out/modules/" + fi + + # Copy libstorage library to modules directory (needed by storage_module_plugin) + if [ -f "${logosStorageModule}/lib/libstorage.$OS_EXT" ]; then + cp -L "${logosStorageModule}/lib/libstorage.$OS_EXT" "$out/modules/" + fi + + runHook postInstall + ''; +}