Merge pull request #230 from sfackler/default-no-std

Restructure initialization setup
This commit is contained in:
Alex Crichton
2017-10-04 10:59:46 +02:00
committed by GitHub
6 changed files with 56 additions and 144 deletions
+2 -9
View File
@@ -4,22 +4,15 @@ rust:
- stable
- beta
- nightly
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build --verbose
- cargo build --verbose --features serde
- cargo build --verbose --no-default-features
- cargo build --verbose --features use_std
- cargo test --verbose
- cargo test --verbose --features serde
- cargo test --verbose --no-default-features
- cargo test --verbose --features use_std
- cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml
- cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml --release
after_success:
- travis-cargo --only nightly doc-upload
env:
global:
secure: "VPHgnszydMudYTY8cthHj/Dmxqp7OmTiu4Sa/705Udsx+tYblTv+8WdThkClo3C/asStVcxlaRWAp91UX32/k4SfkPz17XId3Wadyt03r73ANm6ZOWY+qty+3/LINm54kuTxYUDDTbD6NaFNPFQLIE0xCpJeiXUQTlaMk6z0W3M="
notifications:
email:
+3 -1
View File
@@ -15,6 +15,9 @@ categories = ["development-tools::debugging"]
keywords = ["logging"]
publish = false # this branch contains breaking changes
[package.metadata.docs.rs]
features = ["use_std"]
[[test]]
name = "filters"
harness = false
@@ -35,7 +38,6 @@ release_max_level_debug = []
release_max_level_trace = []
use_std = []
default = ["use_std"]
[badges]
travis-ci = { repository = "rust-lang-nursery/log" }
+1
View File
@@ -16,3 +16,4 @@ build: false
test_script:
- cargo test --verbose
- cargo test --verbose --features serde
- cargo test --verbose --features use_std
+42 -126
View File
@@ -150,7 +150,7 @@
//!
//! ```rust
//! # extern crate log;
//! # use log::{Level, LevelFilter, SetLoggerError, Metadata};
//! # use log::{Level, Metadata};
//! # struct SimpleLogger;
//! # impl log::Log for SimpleLogger {
//! # fn enabled(&self, _: &Metadata) -> bool { false }
@@ -158,22 +158,25 @@
//! # fn flush(&self) {}
//! # }
//! # fn main() {}
//! # #[cfg(feature = "use_std")]
//! pub fn init() {
//! let filter = LevelFilter::Info;
//! let logger = Box::new(SimpleLogger);
//! log::set_logger(logger, filter);
//! use log::{SetLoggerError, LevelFilter};
//!
//! static LOGGER: SimpleLogger = SimpleLogger;
//!
//! pub fn init() -> Result<(), SetLoggerError> {
//! log::set_logger(|max_level| {
//! max_level.set(LevelFilter::Info);
//! &LOGGER
//! })
//! }
//! ```
//!
//! # Use with `no_std`
//! # Use with `use_std`
//!
//! To use the `log` crate without depending on `libstd`, you need to specify
//! `default-features = false` when specifying the dependency in `Cargo.toml`.
//! This makes no difference to libraries using `log` since the logging API
//! remains the same. However executables will need to use the [`try_set_logger_raw`]
//! function to initialize a logger and the [`shutdown_logger_raw`] function to
//! shut down the global logger before exiting:
//! `set_logger` requires you to provide a `&'static Log`, which can be hard if
//! your logger depends on some runtime configuration. The `set_boxed_logger`
//! function is available with the `use_std` Cargo feature. It is identical to
//! `set_logger` except that it requires you to provide a `Box<Log>` rather than
//! a `&'static Log`:
//!
//! ```rust
//! # extern crate log;
@@ -185,14 +188,12 @@
//! # fn flush(&self) {}
//! # }
//! # fn main() {}
//! pub fn try_init() -> Result<(), SetLoggerError> {
//! unsafe {
//! log::try_set_logger_raw(|max_level| {
//! static LOGGER: SimpleLogger = SimpleLogger;
//! max_level.set(LevelFilter::Info);
//! &LOGGER
//! })
//! }
//! # #[cfg(feature = "use_std")]
//! pub fn init() -> Result<(), SetLoggerError> {
//! log::set_boxed_logger(|max_level| {
//! max_level.set(LevelFilter::Info);
//! Box::new(SimpleLogger)
//! })
//! }
//! ```
//!
@@ -206,7 +207,7 @@
//!
//! ```toml
//! [dependencies.log]
//! version = "^0.3.7"
//! version = "0.4"
//! features = ["max_level_debug", "release_max_level_warn"]
//! ```
//!
@@ -972,123 +973,42 @@ pub fn max_level() -> LevelFilter {
unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
}
/// Sets the global logger.
/// Sets the global logger to a `Box<Log>`.
///
/// The `make_logger` closure is passed a `MaxLevel` object, which the
/// logger should use to keep the global maximum log level in sync with the
/// highest log level that the logger will not ignore.
/// This is a simple convenience wrapper over `set_logger`, which takes a
/// `Box<Log>` rather than a `&'static Log`. See the documentation for
/// [`set_logger`] for more details.
///
/// This function may only be called once in the lifetime of a program. Any log
/// events that occur before the call to `try_set_logger` completes will be
/// ignored.
///
/// This function does not typically need to be called manually. Logger
/// implementations should provide an initialization method that calls
/// `try_set_logger` internally.
///
/// Requires the `use_std` feature (enabled by default).
/// Requires the `use_std` feature.
///
/// # Errors
///
/// This function fails to set the global logger if it has already
/// been called before.
/// An error is returned if a logger has already been set.
///
/// # Example
///
/// Implements a custom logger `ConsoleLogger` which prints to stdout.
/// In order to use the logging macros, `ConsoleLogger` implements
/// the [`Log`] trait and has to be installed via `set_logger`.
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// #
/// use log::{Record, Level, Metadata, LevelFilter, SetLoggerError};
///
/// struct ConsoleLogger;
///
/// impl log::Log for ConsoleLogger {
/// fn enabled(&self, metadata: &Metadata) -> bool {
/// metadata.level() <= Level::Info
/// }
///
/// fn log(&self, record: &Record) {
/// if self.enabled(record.metadata()) {
/// println!("Rust says: {} - {}", record.level(), record.args());
/// }
/// }
/// fn flush(&self) {}
/// }
///
/// fn try_init() -> Result<(), SetLoggerError> {
/// log::try_set_logger(|max_log_level| {
/// max_log_level.set(LevelFilter::Info);
/// Box::new(ConsoleLogger)
/// });
///
/// info!("hello log");
/// warn!("warning");
/// error!("oops");
/// Ok(())
/// }
/// #
/// # fn main(){}
/// ```
///
/// [`Log`]: trait.Log.html
/// [`set_logger`]: fn.set_logger.html
#[cfg(feature = "use_std")]
pub fn try_set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
pub fn set_boxed_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log>
{
unsafe { try_set_logger_raw(|max_level| &*Box::into_raw(make_logger(max_level))) }
unsafe { set_logger(|max_level| &*Box::into_raw(make_logger(max_level))) }
}
/// Sets the global logger.
///
/// This function may only be called once in the lifetime of a program. Any log
/// events that occur before the call to `set_logger` completes will be
/// ignored.
///
/// This function will panic on future initialization attempts.
///
/// This function does not typically need to be called manually. Logger
/// implementations should provide an initialization method that calls
/// `set_logger` internally.
///
/// Requires the `use_std` feature (enabled by default).
///
/// # Panics
///
/// The function will panic if it is called more than once.
#[cfg(feature = "use_std")]
pub fn set_logger(logger: Box<Log>, filter: LevelFilter) {
match try_set_logger(|max| { max.set(filter); logger }) {
Ok(()) => {}
Err(_) => panic!("global logger is already initialized"),
}
}
/// Sets the global logger from a raw pointer.
///
/// This function is similar to [`set_logger`] except that it is usable in
/// `no_std` code.
/// Sets the global logger to a `&'static Log`.
///
/// The `make_logger` closure is passed a `MaxLevel` object, which the
/// logger should use to keep the global maximum log level in sync with the
/// highest log level that the logger will not ignore.
///
/// This function may only be called once in the lifetime of a program. Any log
/// events that occur before the call to `try_set_logger_raw` completes will be
/// ignored.
/// events that occur before the call to `set_logger` completes will be ignored.
///
/// This function does not typically need to be called manually. Logger
/// implementations should provide an initialization method that calls
/// `try_set_logger_raw` internally.
/// implementations should provide an initialization method that installs the
/// logger internally.
///
/// # Errors
///
/// This function fails to set the global logger if [`set_logger`]
/// has already been called.
/// An error is returned if a logger has already been set.
///
/// # Examples
///
@@ -1098,10 +1018,10 @@ pub fn set_logger(logger: Box<Log>, filter: LevelFilter) {
/// #
/// use log::{Record, Level, Metadata, LevelFilter};
///
/// struct MyLogger;
///
/// static MY_LOGGER: MyLogger = MyLogger;
///
/// struct MyLogger;
///
/// impl log::Log for MyLogger {
/// fn enabled(&self, metadata: &Metadata) -> bool {
/// metadata.level() <= Level::Info
@@ -1116,21 +1036,17 @@ pub fn set_logger(logger: Box<Log>, filter: LevelFilter) {
/// }
///
/// # fn main(){
/// log::try_set_logger_raw(|max_log_level| {
/// log::set_logger(|max_log_level| {
/// max_log_level.set(LevelFilter::Info);
/// &MY_LOGGER
/// });
/// }).unwrap();
///
/// info!("hello log");
/// warn!("warning");
/// error!("oops");
/// # }
/// ```
///
/// [`set_logger`]: fn.set_logger.html
/// [`shutdown_logger`]: fn.shutdown_logger.html
/// [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html
pub fn try_set_logger_raw<M>(make_logger: M) -> Result<(), SetLoggerError>
pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> &'static Log
{
unsafe {
+4 -4
View File
@@ -6,12 +6,12 @@ use log::{Level, LevelFilter, Log, Record, Metadata};
use log::MaxLevelFilter;
#[cfg(feature = "use_std")]
use log::try_set_logger;
use log::set_boxed_logger;
#[cfg(not(feature = "use_std"))]
fn try_set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
fn set_boxed_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log>
{
unsafe { log::try_set_logger_raw(|x| std::mem::transmute(make_logger(x))) }
log::set_logger(|x| unsafe { &*Box::into_raw(make_logger(x)) })
}
struct State {
@@ -34,7 +34,7 @@ impl Log for Logger {
fn main() {
let mut a = None;
try_set_logger(|max| {
set_boxed_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,
+4 -4
View File
@@ -6,12 +6,12 @@ use log::{Level, LevelFilter, Log, Record, Metadata};
use log::MaxLevelFilter;
#[cfg(feature = "use_std")]
use log::try_set_logger;
use log::set_boxed_logger;
#[cfg(not(feature = "use_std"))]
fn try_set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
fn set_boxed_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log> {
unsafe {
log::try_set_logger_raw(|x| std::mem::transmute(make_logger(x)))
log::set_logger(|x| &*Box::into_raw(make_logger(x)))
}
}
@@ -36,7 +36,7 @@ impl Log for Logger {
fn main() {
let mut a = None;
try_set_logger(|max| {
set_boxed_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,