console: Add console subsystem
Change-Id: I2aeead9ecb7cb9fbf5a223d680eb41e6c175d706
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/maize/+/259333
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Reviewed-by: Travis Geiselbrecht <travisg@google.com>
Commit-Queue: Erik Gilling <konkers@google.com>
diff --git a/.bazelrc b/.bazelrc
index 84f3961..b5bd8a6 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -80,7 +80,7 @@
# TODO - konkers: fix upstream stable toolchains
common --@@rules_rust+//rust/toolchain/channel=nightly
-common --@pigweed//pw_log/rust:pw_log_backend=@pigweed//pw_log/rust:pw_log_backend_println
+common --@pigweed//pw_log/rust:pw_log_backend=//subsys/console:pw_log_backend
# Clippy broken with embedded tests
build:qemu-microbit --output_groups=-clippy_checks
diff --git a/arch/arm_cortex_m/spinlock_backend_cortex_m.rs b/arch/arm_cortex_m/spinlock_backend_cortex_m.rs
index 5c88aa6..6086a9d 100644
--- a/arch/arm_cortex_m/spinlock_backend_cortex_m.rs
+++ b/arch/arm_cortex_m/spinlock_backend_cortex_m.rs
@@ -72,6 +72,11 @@
is_locked: UnsafeCell<bool>,
}
+// Safety: Access to `is_locked` is protected by disabling interrupts and
+// proper barriers.
+unsafe impl Send for BareSpinLock {}
+unsafe impl Sync for BareSpinLock {}
+
impl BareSpinLock {
pub const fn new() -> Self {
Self {
diff --git a/lib/pw_status/BUILD.bazel b/lib/pw_status/BUILD.bazel
new file mode 100644
index 0000000..e76a5d3
--- /dev/null
+++ b/lib/pw_status/BUILD.bazel
@@ -0,0 +1,43 @@
+# Copyright 2023 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+load("@pigweed//pw_build:compatibility.bzl", "incompatible_with_mcu")
+load("@rules_rust//rust:defs.bzl", "rust_doc_test", "rust_library", "rust_test")
+
+rust_library(
+ name = "pw_status",
+ srcs = ["pw_status.rs"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@rust_crates//:embedded-io",
+ ],
+)
+
+rust_test(
+ name = "pw_status_test",
+ srcs = ["pw_status_test.rs"],
+ use_libtest_harness = False,
+ visibility = ["//visibility:public"],
+ deps = [
+ ":pw_status",
+ "//lib/unittest",
+ "//target:linker_script",
+ ],
+)
+
+rust_doc_test(
+ name = "pw_status_doc_test",
+ crate = ":pw_status",
+ target_compatible_with = incompatible_with_mcu(),
+)
diff --git a/lib/pw_status/pw_status.rs b/lib/pw_status/pw_status.rs
new file mode 100644
index 0000000..99b8af1
--- /dev/null
+++ b/lib/pw_status/pw_status.rs
@@ -0,0 +1,111 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+//! # pw_status
+//!
+//! Rust error types using error codes compatible with Pigweed's
+//! [pw_status](https://pigweed.dev/pw_status). In order to keep the interface
+//! idiomatic for Rust, `PW_STATUS_OK` is omitted from the Error enum and a
+//! `StatusCode` trait is provided to turn a `Result` into a canonical
+//! status code.
+//!
+//! For an in depth explanation of the values of the `Error` enum, see
+//! the [Pigweed status codes documentation](https://pigweed.dev/pw_status/#status-codes).
+//!
+//! # Example
+//!
+//! ```
+//! use pw_status::{Error, Result};
+//!
+//! fn div(numerator: u32, denominator: u32) -> Result<u32> {
+//! if denominator == 0 {
+//! Err(Error::FailedPrecondition)
+//! } else {
+//! Ok(numerator / denominator)
+//! }
+//! }
+//!
+//! assert_eq!(div(4, 2), Ok(2));
+//! assert_eq!(div(4, 0), Err(Error::FailedPrecondition));
+//! ```
+
+#![no_std]
+
+/// Status code for no error.
+pub const OK: u32 = 0;
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+/// Error type compatible with Pigweed's [pw_status](https://pigweed.dev/pw_status).
+///
+/// For an in depth explanation of the values of the `Error` enum, see
+/// the [Pigweed status codes documentation](https://pigweed.dev/pw_status/#status-codes).
+pub enum Error {
+ Cancelled = 1,
+ Unknown = 2,
+ InvalidArgument = 3,
+ DeadlineExceeded = 4,
+ NotFound = 5,
+ AlreadyExists = 6,
+ PermissionDenied = 7,
+ ResourceExhausted = 8,
+ FailedPrecondition = 9,
+ Aborted = 10,
+ OutOfRange = 11,
+ Unimplemented = 12,
+ Internal = 13,
+ Unavailable = 14,
+ DataLoss = 15,
+ Unauthenticated = 16,
+}
+
+pub type Result<T> = core::result::Result<T, Error>;
+
+/// Convert a Result into an status code.
+pub trait StatusCode {
+ /// Return a pigweed compatible status code.
+ fn status_code(self) -> u32;
+}
+
+impl<T> StatusCode for Result<T> {
+ fn status_code(self) -> u32 {
+ match self {
+ Ok(_) => OK,
+ Err(e) => e as u32,
+ }
+ }
+}
+
+impl embedded_io::Error for Error {
+ fn kind(&self) -> embedded_io::ErrorKind {
+ use embedded_io::ErrorKind;
+ match self {
+ Error::Cancelled => ErrorKind::Interrupted,
+ Error::Unknown => ErrorKind::Other,
+ Error::InvalidArgument => ErrorKind::InvalidInput,
+ Error::DeadlineExceeded => ErrorKind::TimedOut,
+ Error::NotFound => ErrorKind::NotFound,
+ Error::AlreadyExists => ErrorKind::AlreadyExists,
+ Error::PermissionDenied => ErrorKind::PermissionDenied,
+ Error::ResourceExhausted => ErrorKind::OutOfMemory,
+ Error::FailedPrecondition => ErrorKind::InvalidInput,
+ Error::Aborted => ErrorKind::Interrupted,
+ Error::OutOfRange => ErrorKind::InvalidInput,
+ Error::Unimplemented => ErrorKind::Unsupported,
+ Error::Internal => ErrorKind::Unsupported,
+ Error::Unavailable => ErrorKind::Other,
+ Error::DataLoss => ErrorKind::Other,
+ Error::Unauthenticated => ErrorKind::Other,
+ }
+ }
+}
diff --git a/lib/pw_status/pw_status_test.rs b/lib/pw_status/pw_status_test.rs
new file mode 100644
index 0000000..288bf8c
--- /dev/null
+++ b/lib/pw_status/pw_status_test.rs
@@ -0,0 +1,44 @@
+// Copyright 2025 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#![no_std]
+#![no_main]
+
+use pw_status::*;
+use unittest::test;
+
+#[test]
+fn test_status_code() -> core::result::Result<(), unittest::TestError> {
+ unittest::assert_eq!(Result::Ok(()).status_code(), 0);
+ unittest::assert_eq!(Result::<()>::Err(Error::Cancelled).status_code(), 1);
+ unittest::assert_eq!(Result::<()>::Err(Error::Unknown).status_code(), 2);
+ unittest::assert_eq!(Result::<()>::Err(Error::InvalidArgument).status_code(), 3);
+ unittest::assert_eq!(Result::<()>::Err(Error::DeadlineExceeded).status_code(), 4);
+ unittest::assert_eq!(Result::<()>::Err(Error::NotFound).status_code(), 5);
+ unittest::assert_eq!(Result::<()>::Err(Error::AlreadyExists).status_code(), 6);
+ unittest::assert_eq!(Result::<()>::Err(Error::PermissionDenied).status_code(), 7);
+ unittest::assert_eq!(Result::<()>::Err(Error::ResourceExhausted).status_code(), 8);
+ unittest::assert_eq!(
+ Result::<()>::Err(Error::FailedPrecondition).status_code(),
+ 9
+ );
+ unittest::assert_eq!(Result::<()>::Err(Error::Aborted).status_code(), 10);
+ unittest::assert_eq!(Result::<()>::Err(Error::OutOfRange).status_code(), 11);
+ unittest::assert_eq!(Result::<()>::Err(Error::Unimplemented).status_code(), 12);
+ unittest::assert_eq!(Result::<()>::Err(Error::Internal).status_code(), 13);
+ unittest::assert_eq!(Result::<()>::Err(Error::Unavailable).status_code(), 14);
+ unittest::assert_eq!(Result::<()>::Err(Error::DataLoss).status_code(), 15);
+ unittest::assert_eq!(Result::<()>::Err(Error::Unauthenticated).status_code(), 16);
+ Ok(())
+}
diff --git a/subsys/console/BUILD.bazel b/subsys/console/BUILD.bazel
new file mode 100644
index 0000000..24f77a3
--- /dev/null
+++ b/subsys/console/BUILD.bazel
@@ -0,0 +1,99 @@
+# Copyright 2025 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+load("@pigweed//pw_build:compatibility.bzl", "incompatible_with_mcu")
+load("@rules_rust//rust:defs.bzl", "rust_library", "rust_proc_macro")
+
+rust_library(
+ name = "console",
+ srcs = ["console.rs"],
+ deps = [
+ ":console_backend",
+ "//kernel/sync:spinlock",
+ "//lib/pw_status",
+ "@rust_crates//:embedded-io",
+ ],
+)
+
+rust_library(
+ name = "console_backend_stdio",
+ srcs = ["console_backend_stdio.rs"],
+ crate_name = "console_backend",
+ target_compatible_with = incompatible_with_mcu(),
+ deps = [
+ "//lib/pw_status",
+ "@rust_crates//:embedded-io",
+ ],
+)
+
+rust_library(
+ name = "console_backend_semihosting",
+ srcs = ["console_backend_semihosting.rs"],
+ crate_name = "console_backend",
+ target_compatible_with = select({
+ "@pigweed//pw_build/constraints/arm:cortex-m0": [],
+ "@pigweed//pw_build/constraints/arm:cortex-m3": [],
+ "//conditions:default": ["@platforms//:incompatible"],
+ }),
+ deps = [
+ "//lib/pw_status",
+ "@rust_crates//:cortex-m-semihosting",
+ "@rust_crates//:embedded-io",
+ ],
+)
+
+rust_library(
+ name = "console_core",
+ srcs = ["console_core.rs"],
+ deps = [
+ "@rust_crates//:embedded-io",
+ ],
+)
+
+label_flag(
+ name = "console_backend",
+ build_setting_default = ":console_backend_stdio",
+)
+
+rust_proc_macro(
+ name = "pw_log_backend_macro",
+ srcs = [
+ "pw_log_backend_macro.rs",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@pigweed//pw_format/rust:pw_format",
+ "@pigweed//pw_log/rust:pw_log_backend_api",
+ "@pigweed//pw_status/rust:pw_status",
+ "@rust_crates//:proc-macro2",
+ "@rust_crates//:quote",
+ "@rust_crates//:syn",
+ ],
+)
+
+rust_library(
+ name = "pw_log_backend",
+ srcs = [
+ "pw_log_backend.rs",
+ ],
+ crate_name = "pw_log_backend",
+ proc_macro_deps = [":pw_log_backend_macro"],
+ tags = ["manual"],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":console",
+ "@pigweed//pw_log/rust:pw_log_backend_api",
+ "@rust_crates//:embedded-io",
+ ],
+)
diff --git a/subsys/console/console.rs b/subsys/console/console.rs
new file mode 100644
index 0000000..0ef2ee2
--- /dev/null
+++ b/subsys/console/console.rs
@@ -0,0 +1,46 @@
+// Copyright 2025 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License
+
+#![no_std]
+
+use embedded_io::{ErrorType, Write};
+use spinlock::{BareSpinLock, BareSpinLockApi};
+
+use console_backend::ConsoleBackend;
+
+static CONSOLE_SPINLOCK: BareSpinLock = BareSpinLock::new();
+
+pub struct ConsoleLock {
+ _lock: <BareSpinLock as BareSpinLockApi>::Guard<'static>,
+}
+
+impl ErrorType for ConsoleLock {
+ type Error = pw_status::Error;
+}
+
+impl Write for ConsoleLock {
+ fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
+ ConsoleBackend {}.write(buf)
+ }
+
+ fn flush(&mut self) -> Result<(), Self::Error> {
+ ConsoleBackend {}.flush()
+ }
+}
+
+pub fn get_console() -> ConsoleLock {
+ ConsoleLock {
+ _lock: CONSOLE_SPINLOCK.lock(),
+ }
+}
diff --git a/subsys/console/console_backend_semihosting.rs b/subsys/console/console_backend_semihosting.rs
new file mode 100644
index 0000000..542830a
--- /dev/null
+++ b/subsys/console/console_backend_semihosting.rs
@@ -0,0 +1,36 @@
+// Copyright 2025 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License
+
+#![no_std]
+
+use cortex_m_semihosting::hio::hstdout;
+use embedded_io::{ErrorType, Write};
+
+pub struct ConsoleBackend {}
+
+impl ErrorType for ConsoleBackend {
+ type Error = pw_status::Error;
+}
+
+impl Write for ConsoleBackend {
+ fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
+ let mut stdout = hstdout().map_err(|_| Self::Error::Unavailable)?;
+ stdout.write_all(buf).map_err(|_| Self::Error::DataLoss)?;
+ Ok(buf.len())
+ }
+
+ fn flush(&mut self) -> Result<(), Self::Error> {
+ Ok(())
+ }
+}
diff --git a/subsys/console/console_backend_stdio.rs b/subsys/console/console_backend_stdio.rs
new file mode 100644
index 0000000..6ed5eec
--- /dev/null
+++ b/subsys/console/console_backend_stdio.rs
@@ -0,0 +1,33 @@
+// Copyright 2025 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License
+
+use std::io::{stdout, Write as StdWrite};
+
+use embedded_io::{ErrorType, Write};
+
+pub struct ConsoleBackend {}
+
+impl ErrorType for ConsoleBackend {
+ type Error = pw_status::Error;
+}
+
+impl Write for ConsoleBackend {
+ fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
+ stdout().lock().write(buf).map_err(|_| Self::Error::Unknown)
+ }
+
+ fn flush(&mut self) -> Result<(), Self::Error> {
+ stdout().lock().flush().map_err(|_| Self::Error::Unknown)
+ }
+}
diff --git a/subsys/console/console_core.rs b/subsys/console/console_core.rs
new file mode 100644
index 0000000..ae7ce2b
--- /dev/null
+++ b/subsys/console/console_core.rs
@@ -0,0 +1,15 @@
+// Copyright 2025 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License
+
+#![no_std]
diff --git a/target/qemu/pw_log_backend_qemu/pw_log_backend.rs b/subsys/console/pw_log_backend.rs
similarity index 96%
rename from target/qemu/pw_log_backend_qemu/pw_log_backend.rs
rename to subsys/console/pw_log_backend.rs
index 6e81268..f14818f 100644
--- a/target/qemu/pw_log_backend_qemu/pw_log_backend.rs
+++ b/subsys/console/pw_log_backend.rs
@@ -18,6 +18,8 @@
pub mod __private {
pub use pw_log_backend_macro::{_pw_log_backend, _pw_logf_backend};
+ pub use console;
+ pub use embedded_io;
use pw_log_backend_api::LogLevel;
pub const fn log_level_tag(level: LogLevel) -> &'static str {
diff --git a/target/qemu/pw_log_backend_qemu/pw_log_backend_macro.rs b/subsys/console/pw_log_backend_macro.rs
similarity index 88%
rename from target/qemu/pw_log_backend_qemu/pw_log_backend_macro.rs
rename to subsys/console/pw_log_backend_macro.rs
index e5d5ee9..80b1d9a 100644
--- a/target/qemu/pw_log_backend_qemu/pw_log_backend_macro.rs
+++ b/subsys/console/pw_log_backend_macro.rs
@@ -49,7 +49,7 @@
}
// Generator that implements [`pw_format::CoreFmtFormatMacroGenerator`] to take
-// a log line and turn it into [`cortex_m_semihosting::hprintln] calls.
+// a log line output it through the system console.
struct LogfGenerator<'a> {
log_level: &'a Expr,
args: Vec<TokenStream2>,
@@ -64,17 +64,21 @@
}
}
-// Use a [`pw_format::CoreFmtFormatMacroGenerator`] to prepare arguments to call
-// [`cortex_m_semihosting::hprintln`].
impl CoreFmtFormatMacroGenerator for LogfGenerator<'_> {
fn finalize(self, format_string: String) -> Result<TokenStream2> {
let log_level = self.log_level;
let args = &self.args;
- let format_string = format!("[{{}}] {format_string}");
+ let format_string = format!("[{{}}] {format_string}\n");
Ok(quote! {
{
- use cortex_m_semihosting::hprintln;
- hprintln!(#format_string, __pw_log_backend_crate::log_level_tag(#log_level), #(#args),*);
+ use __pw_log_backend_crate::embedded_io::Write;
+ let mut console = __pw_log_backend_crate::console::get_console();
+ let _ = core::write!(
+ &mut console,
+ #format_string,
+ __pw_log_backend_crate::log_level_tag(#log_level),
+ #(#args),*
+ );
}
})
}
diff --git a/target/qemu/BUILD.bazel b/target/qemu/BUILD.bazel
index ec2a5dc..43d64be 100644
--- a/target/qemu/BUILD.bazel
+++ b/target/qemu/BUILD.bazel
@@ -29,7 +29,7 @@
"//lib/unittest:unittest_runner": "//lib/unittest:unittest_runner_cortex_m",
"//kernel/sync:spinlock_backend": "//arch/arm_cortex_m:spinlock_backend_cortex_m",
"//target:linker_script": "//target/qemu/linker_scripts:qemu_lm3s6965_linker_script",
- "@pigweed//pw_log/rust:pw_log_backend": "//target/qemu/pw_log_backend_qemu:pw_log_backend",
+ "//subsys/console:console_backend": "//subsys/console:console_backend_semihosting",
}),
)
@@ -45,6 +45,6 @@
flags = flags_from_dict({
"//kernel/sync:spinlock_backend": "//arch/arm_cortex_m:spinlock_backend_cortex_m",
"//target:linker_script": "//target/qemu/linker_scripts:qemu_nrf51823_linker_script",
- "@pigweed//pw_log/rust:pw_log_backend": "//target/qemu/pw_log_backend_qemu:pw_log_backend",
+ "//subsys/console:console_backend": "//subsys/console:console_backend_semihosting",
}),
)
diff --git a/target/qemu/pw_log_backend_qemu/BUILD.bazel b/target/qemu/pw_log_backend_qemu/BUILD.bazel
deleted file mode 100644
index 744b920..0000000
--- a/target/qemu/pw_log_backend_qemu/BUILD.bazel
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright 2024 The Pigweed Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-
-load("@rules_rust//rust:defs.bzl", "rust_library", "rust_proc_macro")
-
-package(default_visibility = ["//visibility:public"])
-
-rust_proc_macro(
- name = "pw_log_backend_macro",
- srcs = [
- "pw_log_backend_macro.rs",
- ],
- visibility = ["//visibility:public"],
- deps = [
- "@pigweed//pw_format/rust:pw_format",
- "@pigweed//pw_log/rust:pw_log_backend_api",
- "@pigweed//pw_status/rust:pw_status",
- "@rust_crates//:proc-macro2",
- "@rust_crates//:quote",
- "@rust_crates//:syn",
- ],
-)
-
-rust_library(
- name = "pw_log_backend",
- srcs = [
- "pw_log_backend.rs",
- ],
- crate_name = "pw_log_backend",
- proc_macro_deps = [":pw_log_backend_macro"],
- tags = ["manual"],
- visibility = ["//visibility:public"],
- deps = [
- "@pigweed//pw_log/rust:pw_log_backend_api",
- ],
-)