From 5105b3a80f170a74cccc53391a43eb43dd3c081e Mon Sep 17 00:00:00 2001 From: Pawel Rutka Date: Thu, 18 Sep 2025 10:45:13 +0200 Subject: [PATCH 1/4] Log backend for rust frontend This is logger impl that bridges rust log frontend with C++ mw_log implementation Signed-off-by: Pawel Rutka --- .bazelrc | 5 + BUILD | 10 +- MODULE.bazel | 51 ++-- src/mw_log_subscriber/BUILD | 50 ++++ .../examples/config/logging.json | 7 + src/mw_log_subscriber/examples/main.rs | 74 ++++++ src/mw_log_subscriber/src/lib.rs | 221 ++++++++++++++++++ src/mw_log_subscriber/src/mw_log_ffi.cpp | 104 +++++++++ src/mw_log_subscriber/src/mw_log_ffi.rs | 66 ++++++ 9 files changed, 567 insertions(+), 21 deletions(-) create mode 100644 src/mw_log_subscriber/BUILD create mode 100644 src/mw_log_subscriber/examples/config/logging.json create mode 100644 src/mw_log_subscriber/examples/main.rs create mode 100644 src/mw_log_subscriber/src/lib.rs create mode 100644 src/mw_log_subscriber/src/mw_log_ffi.cpp create mode 100644 src/mw_log_subscriber/src/mw_log_ffi.rs diff --git a/.bazelrc b/.bazelrc index 51cac5a..5fb4945 100644 --- a/.bazelrc +++ b/.bazelrc @@ -7,3 +7,8 @@ test --test_output=errors common --registry=https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/ common --registry=https://bcr.bazel.build + +# magic logging configuration +common --@score-baselibs//score/mw/log/detail/flags:KUse_Stub_Implementation_Only=False +common --@score-baselibs//score/mw/log/flags:KRemote_Logging=False +common --@score-baselibs//score/json:base_library=nlohmann diff --git a/BUILD b/BUILD index 473b5d5..1d9e33c 100644 --- a/BUILD +++ b/BUILD @@ -10,9 +10,11 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* - +load("@score_cr_checker//:cr_checker.bzl", "copyright_checker") +load("@score_dash_license_checker//:dash.bzl", "dash_license_checker") load("@score_docs_as_code//:docs.bzl", "docs") -load("@score_tooling//:defs.bzl", "copyright_checker", "dash_license_checker", "setup_starpls", "use_format_targets") +load("@score_format_checker//:macros.bzl", "use_format_targets") +load("@score_starpls_lsp//:starpls.bzl", "setup_starpls") load("//:project_config.bzl", "PROJECT_CONFIG") setup_starpls( @@ -28,8 +30,8 @@ copyright_checker( "//:BUILD", "//:MODULE.bazel", ], - config = "@score_tooling//cr_checker/resources:config", - template = "@score_tooling//cr_checker/resources:templates", + config = "@score_cr_checker//resources:config", + template = "@score_cr_checker//resources:templates", visibility = ["//visibility:public"], ) diff --git a/MODULE.bazel b/MODULE.bazel index 1ec606d..c545ee1 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,8 +11,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* module( - name = "cpp_rust_template_repository", - version = "1.0", + name = "score-mw-log", + version = "0.1", ) bazel_dep(name = "rules_python", version = "1.4.1") @@ -27,31 +27,48 @@ python.toolchain( use_repo(python) # Add GoogleTest dependency -bazel_dep(name = "googletest", version = "1.17.0") +bazel_dep(name = "googletest", version = "1.15.0") # Rust rules for Bazel -bazel_dep(name = "rules_rust", version = "0.63.0") +bazel_dep(name = "rules_rust", version = "0.56.0") + +# Checker rule for CopyRight checks/fixs +bazel_dep(name = "score_cr_checker", version = "0.3.1") +bazel_dep(name = "score_python_basics", version = "0.3.4") +bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # C/C++ rules for Bazel -bazel_dep(name = "rules_cc", version = "0.2.1") +bazel_dep(name = "rules_cc", version = "0.1.1") # LLVM Toolchains Rules - host configuration -bazel_dep(name = "toolchains_llvm", version = "1.4.0") +bazel_dep(name = "toolchains_llvm", version = "1.3.0") + +# Configure and register the toolchain. +bazel_dep(name = "score_toolchains_gcc", version = "0.4", dev_dependency = True) -llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") -llvm.toolchain( - cxx_standard = {"": "c++17"}, - llvm_version = "19.1.0", +gcc = use_extension("@score_toolchains_gcc//extentions:gcc.bzl", "gcc", dev_dependency = True) +gcc.toolchain( + sha256 = "457f5f20f57528033cb840d708b507050d711ae93e009388847e113b11bf3600", + strip_prefix = "x86_64-unknown-linux-gnu", + url = "https://github.com/eclipse-score/toolchains_gcc_packages/releases/download/0.0.1/x86_64-unknown-linux-gnu_gcc12.tar.gz", ) -use_repo(llvm, "llvm_toolchain") -use_repo(llvm, "llvm_toolchain_llvm") +use_repo(gcc, "gcc_toolchain", "gcc_toolchain_gcc") -register_toolchains("@llvm_toolchain//:all") +# Dash license checker +bazel_dep(name = "score_dash_license_checker", version = "0.1.2") -# tooling -bazel_dep(name = "score_tooling", version = "1.0.1") -bazel_dep(name = "aspect_rules_lint", version = "1.5.3") +# Format checker +bazel_dep(name = "score_format_checker", version = "0.1.1") +bazel_dep(name = "aspect_rules_lint", version = "1.4.4") bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2") #docs-as-code -bazel_dep(name = "score_docs_as_code", version = "1.1.0") +bazel_dep(name = "score_docs_as_code", version = "1.0.1") + +# Code deps +bazel_dep(name = "score-baselibs", version = "0.1.0") +git_override( + module_name = "score-baselibs", + commit = "ae050e3cc556572830e1ec02ffbcbbd03f26df13", # or use "tag" or "branch" + remote = "https://github.com/eclipse-score/baselibs.git", +) diff --git a/src/mw_log_subscriber/BUILD b/src/mw_log_subscriber/BUILD new file mode 100644 index 0000000..7e52aa3 --- /dev/null +++ b/src/mw_log_subscriber/BUILD @@ -0,0 +1,50 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_rust//cargo:defs.bzl", "cargo_build_script") +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") + +cc_library( + name = "libmw_log_ffi", + srcs = ["src/mw_log_ffi.cpp"], + visibility = ["//visibility:public"], + deps = [ + "@score-baselibs//score/mw/log", + ], +) + +rust_library( + name = "mw_log_subscriber", + srcs = glob(["src/**/*.rs"]), + crate_name = "mw_log_subscriber", + edition = "2021", + visibility = ["//visibility:public"], + deps = [ + ":libmw_log_ffi", + "@score-baselibs//score/mw/log/rust:mw_log", + ], +) + +rust_binary( + name = "example", + srcs = ["examples/main.rs"], + data = [ + "examples/config/logging.json", + ], + edition = "2021", + visibility = ["//visibility:public"], + deps = [ + ":mw_log_subscriber", + "@score-baselibs//score/mw/log/rust:mw_log", + ], +) diff --git a/src/mw_log_subscriber/examples/config/logging.json b/src/mw_log_subscriber/examples/config/logging.json new file mode 100644 index 0000000..cf4f333 --- /dev/null +++ b/src/mw_log_subscriber/examples/config/logging.json @@ -0,0 +1,7 @@ +{ + "appId": "JSON", + "appDesc": "JSON example programs", + "logMode" : "kConsole", + "logLevel": "kVerbose", + "logLevelThresholdConsole": "kInfo" +} diff --git a/src/mw_log_subscriber/examples/main.rs b/src/mw_log_subscriber/examples/main.rs new file mode 100644 index 0000000..42264a0 --- /dev/null +++ b/src/mw_log_subscriber/examples/main.rs @@ -0,0 +1,74 @@ +// +// Copyright (c) 2025 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// + +use std::path::PathBuf; + +use mw_log::{debug, error, info, trace, warn}; +use mw_log_subscriber::MwLoggerBuilder; + +fn main() { + //Setup for example using config file + let path = PathBuf::from(std::env::current_dir().unwrap()) + .join(file!()) + .parent() + .unwrap() + .join("config") + .join("logging.json"); + + std::env::set_var("MW_LOG_CONFIG_FILE", path.as_os_str()); + + // Just initialize and set as default logger + MwLoggerBuilder::new().set_as_default_logger::(); + + trace!("This is a trace log"); + debug!("This is a debug log"); + error!("This is an error log"); + info!("This is an info log"); + warn!("This is a warn log"); + + error!( + "This is an log that will be trimmed: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd + eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg + END MARKER NOT VISIBLE" + ); + + error!( + "This is an log that will be trimmed {} {} {} {} {} {} {}. END MARKER NOT VISIBLE", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" + ); + + // Using logger instance with context + let logger = MwLoggerBuilder::new() + .with_context("ALFA") + .build::(); + + trace!( + logger : logger, + "This is a trace log" + ); + debug!(logger : logger, "This is a debug log"); + error!(logger : logger, "This is an error log"); + info!(logger : logger, "This is an info log"); + warn!(logger : logger, "This is a warn log"); +} diff --git a/src/mw_log_subscriber/src/lib.rs b/src/mw_log_subscriber/src/lib.rs new file mode 100644 index 0000000..22c19e1 --- /dev/null +++ b/src/mw_log_subscriber/src/lib.rs @@ -0,0 +1,221 @@ +// +// Copyright (c) 2025 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// + +mod mw_log_ffi; + +use crate::mw_log_ffi::*; + +use core::ffi::c_char; +use core::fmt::{self, Write}; +use mw_log::{Level, Log, Metadata, Record}; +use std::ffi::CString; +use std::mem::MaybeUninit; + +const MSG_SIZE: usize = 512; + +/// Builder for the MwLogger +pub struct MwLoggerBuilder { + context: Option, +} + +impl MwLoggerBuilder { + pub fn new() -> Self { + Self { context: None } + } + + /// Builds the MwLogger with the specified context and configuration and returns it. + pub fn build( + self, + ) -> MwLogger { + let context_cstr = self.context.unwrap_or(CString::new("DFLT").unwrap()); + let c_logger_ptr = unsafe { mw_log_create_logger(context_cstr.as_ptr() as *const _) }; + MwLogger { + ptr: c_logger_ptr, + log_fn: log::, + } + } + + /// Builds and sets the MwLogger as the default logger with the specified configuration. + pub fn set_as_default_logger< + const SHOW_MODULE: bool, + const SHOW_FILE: bool, + const SHOW_LINE: bool, + >( + self, + ) { + let logger = self.build::(); + mw_log::set_max_level(mw_log_logger_level(logger.ptr)); + mw_log::set_boxed_logger(Box::new(logger)) + .expect("Failed to initialize MwLogger as default logger - logger may already be set"); + } + + /// Sets the context for currently build logger. + pub fn with_context(mut self, context: &str) -> Self { + self.context = Some(CString::new(context).expect( + "Failed to create CString: + input contains null bytes", + )); + self + } +} + +/// A simple buffer writer that implements `core::fmt::Write` +/// and writes into a fixed-size(`BUF_SIZE) buffer. +/// Used in `Log` implementation to format log messages +/// before passing them to the underlying C++ logger. +struct BufWriter { + buf: [MaybeUninit; BUF_SIZE], + pos: usize, +} + +impl BufWriter { + fn new() -> Self { + Self { + buf: [MaybeUninit::uninit(); BUF_SIZE], + pos: 0, + } + } + + /// Returns a slice to filled part of buffer. This is not null-terminated. + fn as_slice(&self) -> &[c_char] { + // SAFETY: We only expose already initialized part of the buffer + unsafe { core::slice::from_raw_parts(self.buf.as_ptr().cast::(), self.len()) } + } + + /// Returns the current length of the filled part of the buffer. + fn len(&self) -> usize { + self.pos + } + + /// Reverts the current position (consumes) by `cnt` bytes, saturating at 0. + fn revert_pos(&mut self, cnt: usize) { + self.pos = self.pos.saturating_sub(cnt); + } + + // Finds the right index (around requested `index`) to trim utf8 string to a valid char boundary + fn floor_char_boundary(view: &str, index: usize) -> usize { + if index >= view.len() { + view.len() + } else { + let lower_bound = index.saturating_sub(3); + let new_index = view.as_bytes()[lower_bound..=index] + .iter() + .rposition(|b| Self::is_utf8_char_boundary(*b)); + + // SAFETY: we know that the character boundary will be within four bytes + unsafe { lower_bound + new_index.unwrap_unchecked() } + } + } + + const fn is_utf8_char_boundary(i: u8) -> bool { + // This is bit magic equivalent to: b < 128 || b >= 192 + (i as i8) >= -0x40 + } +} + +impl Write for BufWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + let bytes = s.as_bytes(); + let to_write = bytes.len().min(self.buf.len() - self.pos - 1); // Cutting write, instead error when we don't fit + let bounded_to_write = Self::floor_char_boundary(s, to_write); + + if bounded_to_write == 0 { + return Err(fmt::Error); + } + + let dest = self.buf[self.pos..self.pos + bounded_to_write] + .as_mut_ptr() + .cast::(); + + unsafe { core::ptr::copy_nonoverlapping(bytes.as_ptr(), dest, bounded_to_write) }; + + self.pos += bounded_to_write; + Ok(()) + } +} + +pub struct MwLogger { + ptr: *const Logger, + log_fn: fn(&mut BufWriter, &Record), +} + +// SAFETY: The underlying C++ logger is known to be safe to change thread +unsafe impl Send for MwLogger {} + +// SAFETY: The underlying C++ logger is known to be thread-safe. +unsafe impl Sync for MwLogger {} + +impl MwLogger { + fn write_log(&self, level: Level, msg: &BufWriter) { + let slice = msg.as_slice(); + + unsafe { + match level { + Level::Error => mw_log_error_logger(self.ptr, slice.as_ptr(), slice.len() as u32), + Level::Warn => mw_log_warn_logger(self.ptr, slice.as_ptr(), slice.len() as u32), + Level::Info => mw_log_info_logger(self.ptr, slice.as_ptr(), slice.len() as u32), + Level::Debug => mw_log_debug_logger(self.ptr, slice.as_ptr(), slice.len() as u32), + Level::Trace => mw_log_verbose_logger(self.ptr, slice.as_ptr(), slice.len() as u32), + } + } + } +} + +impl Log for MwLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + mw_log_is_log_level_enabled(self.ptr, metadata.level()) + } + fn log(&self, record: &Record) { + if !self.enabled(record.metadata()) { + return; + } + + let mut msg_writer = BufWriter::::new(); + (self.log_fn)(&mut msg_writer, record); + + self.write_log(record.level(), &msg_writer); + } + + fn flush(&self) { + // No-op for this logger, as it does not buffer logs + } +} + +fn log( + msg_writer: &mut BufWriter, + record: &Record, +) { + if SHOW_FILE || SHOW_LINE || SHOW_MODULE { + let _ = write!(msg_writer, "["); + if SHOW_MODULE { + if let Some(module) = record.module_path() { + let _ = write!(msg_writer, "{}:", module); + } + } + if SHOW_FILE { + if let Some(file) = record.file() { + let _ = write!(msg_writer, "{}:", file); + } + } + if SHOW_LINE { + if let Some(line) = record.line() { + let _ = write!(msg_writer, "{}:", line); + } + } + + msg_writer.revert_pos(1); + let _ = write!(msg_writer, "] "); + } + + let _ = msg_writer.write_fmt(*record.args()); +} diff --git a/src/mw_log_subscriber/src/mw_log_ffi.cpp b/src/mw_log_subscriber/src/mw_log_ffi.cpp new file mode 100644 index 0000000..dc7544a --- /dev/null +++ b/src/mw_log_subscriber/src/mw_log_ffi.cpp @@ -0,0 +1,104 @@ +/******************************************************************************** +* Copyright (c) 2025 Contributors to the Eclipse Foundation +* +* See the NOTICE file(s) distributed with this work for additional +* information regarding copyright ownership. +* +* This program and the accompanying materials are made available under the +* terms of the Apache License Version 2.0 which is available at +* https://www.apache.org/licenses/LICENSE-2.0 +* +* SPDX-License-Identifier: Apache-2.0 +********************************************************************************/ +#include "score/mw/log/logging.h" +#include "score/mw/log/configuration/configuration.h" +#include "score/mw/log/logger.h" +#include "score/mw/log/log_level.h" + +namespace score::mw::log +{ + extern "C" + { + + Logger *mw_log_create_logger(const char *context) + { + return &CreateLogger(context); + } + + bool mw_log_is_log_level_enabled_internal(const Logger *logger, uint8_t level) + { + return logger->IsLogEnabled(GetLogLevelFromU8(level)); + } + + void mw_log_fatal_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogFatal() << LogString{message, size}; + } + + void mw_log_error_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogError() << LogString{message, size}; + } + + void mw_log_warn_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogWarn() << LogString{message, size}; + } + + void mw_log_info_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogInfo() << LogString{message, size}; + } + + void mw_log_debug_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogDebug() << LogString{message, size}; + } + + void mw_log_verbose_logger(const Logger *logger, const char *message, uint32_t size) + { + logger->LogVerbose() << LogString{message, size}; + } + + uint8_t mw_log_logger_level_internal(const Logger *logger) + { + // TODO: This is adapter code, as there seems to be no way to get log level for Logger + if (logger->IsLogEnabled(LogLevel::kInfo)) + { + // Between Verbose, Debug, Info + if (logger->IsLogEnabled(LogLevel::kDebug)) + { + if (logger->IsLogEnabled(LogLevel::kVerbose)) + { + return static_cast(LogLevel::kVerbose); + } + + return static_cast(LogLevel::kDebug); + } + + return static_cast(LogLevel::kInfo); + } + else + { + // Lower half: Warn, Error, Fatal + if (logger->IsLogEnabled(LogLevel::kError)) + { + if (logger->IsLogEnabled(LogLevel::kWarn)) + { + return static_cast(LogLevel::kWarn); + } + + return static_cast(LogLevel::kError); + } + + if (logger->IsLogEnabled(LogLevel::kFatal)) + { + return static_cast(LogLevel::kFatal); + } + } + + // fallback + return static_cast(LogLevel::kOff); + } + } +} // namespace score::mw::log diff --git a/src/mw_log_subscriber/src/mw_log_ffi.rs b/src/mw_log_subscriber/src/mw_log_ffi.rs new file mode 100644 index 0000000..7c2bd12 --- /dev/null +++ b/src/mw_log_subscriber/src/mw_log_ffi.rs @@ -0,0 +1,66 @@ +// +// Copyright (c) 2025 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// + +use core::ffi::c_char; + +use mw_log::{Level, LevelFilter}; + +// Opaque type representing the C++ logger ptr +#[repr(C)] +pub(crate) struct Logger { + _private: [u8; 0], // Opaque +} + +pub(crate) fn mw_log_logger_level(logger: *const Logger) -> LevelFilter { + let level = unsafe { mw_log_logger_level_internal(logger) }; + log_level_from_ffi(level) +} + +pub(crate) fn mw_log_is_log_level_enabled(logger: *const Logger, level: Level) -> bool { + let level_byte = match level { + Level::Error => 0x02, + Level::Warn => 0x03, + Level::Info => 0x04, + Level::Debug => 0x05, + Level::Trace => 0x06, + }; + unsafe { mw_log_is_log_level_enabled_internal(logger, level_byte) } +} + +/// Get the max log level from C++ as a LevelFilter directly +fn log_level_from_ffi(level: u8) -> LevelFilter { + match level { + 0x00 => LevelFilter::Off, + 0x01 => LevelFilter::Error, // Currently Fatal treated as Error + 0x02 => LevelFilter::Error, + 0x03 => LevelFilter::Warn, + 0x04 => LevelFilter::Info, + 0x05 => LevelFilter::Debug, + 0x06 => LevelFilter::Trace, // Verbose is Trace + _ => LevelFilter::Info, // fallback + } +} + +extern "C" { + + pub(crate) fn mw_log_create_logger(context: *const c_char) -> *mut Logger; + pub(crate) fn mw_log_error_logger(logger: *const Logger, message: *const c_char, len: u32); + pub(crate) fn mw_log_warn_logger(logger: *const Logger, message: *const c_char, len: u32); + pub(crate) fn mw_log_info_logger(logger: *const Logger, message: *const c_char, len: u32); + pub(crate) fn mw_log_debug_logger(logger: *const Logger, message: *const c_char, len: u32); + pub(crate) fn mw_log_verbose_logger(logger: *const Logger, message: *const c_char, len: u32); + + fn mw_log_is_log_level_enabled_internal(logger: *const Logger, level: u8) -> bool; + fn mw_log_logger_level_internal(logger: *const Logger) -> u8; + +} From 02f33dbe8bd97c9cfa4c90881e63641d23fad3a0 Mon Sep 17 00:00:00 2001 From: Pawel Rutka Date: Wed, 8 Oct 2025 10:25:55 +0200 Subject: [PATCH 2/4] Adress review findings --- src/mw_log_subscriber/BUILD | 8 ++++---- src/mw_log_subscriber/src/lib.rs | 2 +- .../src/{mw_log_ffi.cpp => rust_cpp_log_adapter.cpp} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename src/mw_log_subscriber/src/{mw_log_ffi.cpp => rust_cpp_log_adapter.cpp} (100%) diff --git a/src/mw_log_subscriber/BUILD b/src/mw_log_subscriber/BUILD index 7e52aa3..f337be5 100644 --- a/src/mw_log_subscriber/BUILD +++ b/src/mw_log_subscriber/BUILD @@ -15,9 +15,9 @@ load("@rules_rust//cargo:defs.bzl", "cargo_build_script") load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") cc_library( - name = "libmw_log_ffi", - srcs = ["src/mw_log_ffi.cpp"], - visibility = ["//visibility:public"], + name = "librust_cpp_log_adapter", + srcs = ["src/rust_cpp_log_adapter.cpp"], + visibility = ["//visibility:private"], deps = [ "@score-baselibs//score/mw/log", ], @@ -30,7 +30,7 @@ rust_library( edition = "2021", visibility = ["//visibility:public"], deps = [ - ":libmw_log_ffi", + ":librust_cpp_log_adapter", "@score-baselibs//score/mw/log/rust:mw_log", ], ) diff --git a/src/mw_log_subscriber/src/lib.rs b/src/mw_log_subscriber/src/lib.rs index 22c19e1..92ef328 100644 --- a/src/mw_log_subscriber/src/lib.rs +++ b/src/mw_log_subscriber/src/lib.rs @@ -38,7 +38,7 @@ impl MwLoggerBuilder { self, ) -> MwLogger { let context_cstr = self.context.unwrap_or(CString::new("DFLT").unwrap()); - let c_logger_ptr = unsafe { mw_log_create_logger(context_cstr.as_ptr() as *const _) }; + let c_logger_ptr = unsafe { mw_log_create_logger(context_cstr.as_ptr().cast::()) }; MwLogger { ptr: c_logger_ptr, log_fn: log::, diff --git a/src/mw_log_subscriber/src/mw_log_ffi.cpp b/src/mw_log_subscriber/src/rust_cpp_log_adapter.cpp similarity index 100% rename from src/mw_log_subscriber/src/mw_log_ffi.cpp rename to src/mw_log_subscriber/src/rust_cpp_log_adapter.cpp From 8383eedbd84298a88ac73d427e5cca6da97822f0 Mon Sep 17 00:00:00 2001 From: Pawel Rutka Date: Tue, 14 Oct 2025 12:05:21 +0200 Subject: [PATCH 3/4] Adapt to cpp/rust structure as in persistency --- src/cpp/.gitkeep | 0 src/{ => rust}/mw_log_subscriber/BUILD | 0 src/{ => rust}/mw_log_subscriber/examples/config/logging.json | 0 src/{ => rust}/mw_log_subscriber/examples/main.rs | 0 src/{ => rust}/mw_log_subscriber/src/lib.rs | 0 src/{ => rust}/mw_log_subscriber/src/mw_log_ffi.rs | 0 src/{ => rust}/mw_log_subscriber/src/rust_cpp_log_adapter.cpp | 0 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/cpp/.gitkeep rename src/{ => rust}/mw_log_subscriber/BUILD (100%) rename src/{ => rust}/mw_log_subscriber/examples/config/logging.json (100%) rename src/{ => rust}/mw_log_subscriber/examples/main.rs (100%) rename src/{ => rust}/mw_log_subscriber/src/lib.rs (100%) rename src/{ => rust}/mw_log_subscriber/src/mw_log_ffi.rs (100%) rename src/{ => rust}/mw_log_subscriber/src/rust_cpp_log_adapter.cpp (100%) diff --git a/src/cpp/.gitkeep b/src/cpp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/mw_log_subscriber/BUILD b/src/rust/mw_log_subscriber/BUILD similarity index 100% rename from src/mw_log_subscriber/BUILD rename to src/rust/mw_log_subscriber/BUILD diff --git a/src/mw_log_subscriber/examples/config/logging.json b/src/rust/mw_log_subscriber/examples/config/logging.json similarity index 100% rename from src/mw_log_subscriber/examples/config/logging.json rename to src/rust/mw_log_subscriber/examples/config/logging.json diff --git a/src/mw_log_subscriber/examples/main.rs b/src/rust/mw_log_subscriber/examples/main.rs similarity index 100% rename from src/mw_log_subscriber/examples/main.rs rename to src/rust/mw_log_subscriber/examples/main.rs diff --git a/src/mw_log_subscriber/src/lib.rs b/src/rust/mw_log_subscriber/src/lib.rs similarity index 100% rename from src/mw_log_subscriber/src/lib.rs rename to src/rust/mw_log_subscriber/src/lib.rs diff --git a/src/mw_log_subscriber/src/mw_log_ffi.rs b/src/rust/mw_log_subscriber/src/mw_log_ffi.rs similarity index 100% rename from src/mw_log_subscriber/src/mw_log_ffi.rs rename to src/rust/mw_log_subscriber/src/mw_log_ffi.rs diff --git a/src/mw_log_subscriber/src/rust_cpp_log_adapter.cpp b/src/rust/mw_log_subscriber/src/rust_cpp_log_adapter.cpp similarity index 100% rename from src/mw_log_subscriber/src/rust_cpp_log_adapter.cpp rename to src/rust/mw_log_subscriber/src/rust_cpp_log_adapter.cpp From 860b8dc089e080b8e0f9409336f1b8e255c0f9be Mon Sep 17 00:00:00 2001 From: Pawel Rutka Date: Thu, 23 Oct 2025 12:38:08 +0200 Subject: [PATCH 4/4] Align to baselibs --- MODULE.bazel | 35 ++++++++++++++++---- src/rust/mw_log_subscriber/BUILD | 9 +++-- src/rust/mw_log_subscriber/examples/main.rs | 2 +- src/rust/mw_log_subscriber/src/lib.rs | 6 ++-- src/rust/mw_log_subscriber/src/mw_log_ffi.rs | 2 +- 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index c545ee1..18fe04f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -19,7 +19,7 @@ bazel_dep(name = "rules_python", version = "1.4.1") PYTHON_VERSION = "3.12" -python = use_extension("@rules_python//python/extensions:python.bzl", "python") +python = use_extension("@rules_python//python/extensions:python.bzl", "python", dev_dependency = True) python.toolchain( is_default = True, python_version = PYTHON_VERSION, @@ -30,7 +30,7 @@ use_repo(python) bazel_dep(name = "googletest", version = "1.15.0") # Rust rules for Bazel -bazel_dep(name = "rules_rust", version = "0.56.0") +bazel_dep(name = "rules_rust", version = "0.61.0") # Checker rule for CopyRight checks/fixs bazel_dep(name = "score_cr_checker", version = "0.3.1") @@ -40,10 +40,7 @@ bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # C/C++ rules for Bazel bazel_dep(name = "rules_cc", version = "0.1.1") -# LLVM Toolchains Rules - host configuration -bazel_dep(name = "toolchains_llvm", version = "1.3.0") - -# Configure and register the toolchain. +# Configure the host toolchain. bazel_dep(name = "score_toolchains_gcc", version = "0.4", dev_dependency = True) gcc = use_extension("@score_toolchains_gcc//extentions:gcc.bzl", "gcc", dev_dependency = True) @@ -52,8 +49,30 @@ gcc.toolchain( strip_prefix = "x86_64-unknown-linux-gnu", url = "https://github.com/eclipse-score/toolchains_gcc_packages/releases/download/0.0.1/x86_64-unknown-linux-gnu_gcc12.tar.gz", ) +gcc.extra_features( + features = [ + "minimal_warnings", + "treat_warnings_as_errors", + ], +) +gcc.warning_flags( + minimal_warnings = [ + "-Wall", + "-Wno-error=deprecated-declarations", + "-Wno-error=narrowing", + ], + strict_warnings = [ + "-Wextra", + "-Wpedantic", + ], +) use_repo(gcc, "gcc_toolchain", "gcc_toolchain_gcc") +register_toolchains( + "@gcc_toolchain//:host_gcc_12", + dev_dependency = True, +) + # Dash license checker bazel_dep(name = "score_dash_license_checker", version = "0.1.2") @@ -69,6 +88,8 @@ bazel_dep(name = "score_docs_as_code", version = "1.0.1") bazel_dep(name = "score-baselibs", version = "0.1.0") git_override( module_name = "score-baselibs", - commit = "ae050e3cc556572830e1ec02ffbcbbd03f26df13", # or use "tag" or "branch" + commit = "c2d9b7e872c1e67b69256214a75c937e00d03601", # or use "tag" or "branch" remote = "https://github.com/eclipse-score/baselibs.git", ) + +# bazel_dep(name = "score_crates", version = "0.0.3") diff --git a/src/rust/mw_log_subscriber/BUILD b/src/rust/mw_log_subscriber/BUILD index f337be5..52b3409 100644 --- a/src/rust/mw_log_subscriber/BUILD +++ b/src/rust/mw_log_subscriber/BUILD @@ -31,7 +31,7 @@ rust_library( visibility = ["//visibility:public"], deps = [ ":librust_cpp_log_adapter", - "@score-baselibs//score/mw/log/rust:mw_log", + "@score-baselibs//score/mw/log/rust:log", ], ) @@ -42,9 +42,14 @@ rust_binary( "examples/config/logging.json", ], edition = "2021", + rustc_flags = [ + "-Clink-arg=-lstdc++", + "-Clink-arg=-lm", + "-Clink-arg=-lc", + ], visibility = ["//visibility:public"], deps = [ ":mw_log_subscriber", - "@score-baselibs//score/mw/log/rust:mw_log", + "@score-baselibs//score/mw/log/rust:log", ], ) diff --git a/src/rust/mw_log_subscriber/examples/main.rs b/src/rust/mw_log_subscriber/examples/main.rs index 42264a0..169686d 100644 --- a/src/rust/mw_log_subscriber/examples/main.rs +++ b/src/rust/mw_log_subscriber/examples/main.rs @@ -13,7 +13,7 @@ use std::path::PathBuf; -use mw_log::{debug, error, info, trace, warn}; +use log::{debug, error, info, trace, warn}; use mw_log_subscriber::MwLoggerBuilder; fn main() { diff --git a/src/rust/mw_log_subscriber/src/lib.rs b/src/rust/mw_log_subscriber/src/lib.rs index 92ef328..410994f 100644 --- a/src/rust/mw_log_subscriber/src/lib.rs +++ b/src/rust/mw_log_subscriber/src/lib.rs @@ -17,7 +17,7 @@ use crate::mw_log_ffi::*; use core::ffi::c_char; use core::fmt::{self, Write}; -use mw_log::{Level, Log, Metadata, Record}; +use log::{Level, Log, Metadata, Record}; use std::ffi::CString; use std::mem::MaybeUninit; @@ -54,8 +54,8 @@ impl MwLoggerBuilder { self, ) { let logger = self.build::(); - mw_log::set_max_level(mw_log_logger_level(logger.ptr)); - mw_log::set_boxed_logger(Box::new(logger)) + log::set_max_level(mw_log_logger_level(logger.ptr)); + log::set_boxed_logger(Box::new(logger)) .expect("Failed to initialize MwLogger as default logger - logger may already be set"); } diff --git a/src/rust/mw_log_subscriber/src/mw_log_ffi.rs b/src/rust/mw_log_subscriber/src/mw_log_ffi.rs index 7c2bd12..339fc84 100644 --- a/src/rust/mw_log_subscriber/src/mw_log_ffi.rs +++ b/src/rust/mw_log_subscriber/src/mw_log_ffi.rs @@ -13,7 +13,7 @@ use core::ffi::c_char; -use mw_log::{Level, LevelFilter}; +use log::{Level, LevelFilter}; // Opaque type representing the C++ logger ptr #[repr(C)]