Commit 87d79eb9 authored by Gabi Melman's avatar Gabi Melman Committed by GitHub

Merge pull request #277 from hghwng/master

Fix compilation on Android.
parents 59bf37f7 96267654
# Auto generated files # Auto generated files
*.slo *.slo
*.lo *.lo
*.o *.o
...@@ -46,6 +46,7 @@ example/* ...@@ -46,6 +46,7 @@ example/*
!example/example.vcxproj !example/example.vcxproj
!example/CMakeLists.txt !example/CMakeLists.txt
!example/multisink.cpp !example/multisink.cpp
!example/jni
# generated files # generated files
generated generated
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
void async_example(); void async_example();
void syslog_example(); void syslog_example();
void android_example();
void user_defined_example(); void user_defined_example();
void err_handler_example(); void err_handler_example();
...@@ -48,7 +49,6 @@ int main(int, char*[]) ...@@ -48,7 +49,6 @@ int main(int, char*[])
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt"); auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt");
my_logger->info("Some log message"); my_logger->info("Some log message");
// Create a file rotating logger with 5mb size max and 3 rotated files // Create a file rotating logger with 5mb size max and 3 rotated files
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/mylogfile", 1048576 * 5, 3); auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/mylogfile", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
...@@ -76,6 +76,9 @@ int main(int, char*[]) ...@@ -76,6 +76,9 @@ int main(int, char*[])
// syslog example. linux/osx only // syslog example. linux/osx only
syslog_example(); syslog_example();
// android example. compile with NDK
android_example();
// Log user-defined types example // Log user-defined types example
user_defined_example(); user_defined_example();
...@@ -119,6 +122,16 @@ void syslog_example() ...@@ -119,6 +122,16 @@ void syslog_example()
#endif #endif
} }
// Android example
void android_example()
{
#if defined(__ANDROID__)
std::string tag = "spdlog-android";
auto android_logger = spd::android_logger("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
#endif
}
// user defined types logging by implementing operator<< // user defined types logging by implementing operator<<
struct my_type struct my_type
{ {
...@@ -148,4 +161,3 @@ void err_handler_example() ...@@ -148,4 +161,3 @@ void err_handler_example()
}); });
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3); spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
} }
# Setup a project
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_SRC_FILES := example.cpp
LOCAL_CPPFLAGS += -Wall -Wshadow -Wextra -pedantic -std=c++11 -fPIE -pie
LOCAL_LDFLAGS += -fPIE -pie
# Add exception support and set path for spdlog's headers
LOCAL_CPPFLAGS += -fexceptions -I../include
# Use android's log library
LOCAL_LDFLAGS += -llog
include $(BUILD_EXECUTABLE)
# Exceptions are used in spdlog. Link to an exception-ready C++ runtime.
APP_STL = gnustl_static
../example.cpp
\ No newline at end of file
...@@ -342,7 +342,9 @@ inline std::string errno_str(int err_num) ...@@ -342,7 +342,9 @@ inline std::string errno_str(int err_num)
else else
return "Unkown error"; return "Unkown error";
#elif defined(__FreeBSD__) || defined(__APPLE__) || ((_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE) // posix version #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || \
((_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE) // posix version
if (strerror_r(err_num, buf, buf_size) == 0) if (strerror_r(err_num, buf, buf_size) == 0)
return std::string(buf); return std::string(buf);
else else
...@@ -356,5 +358,3 @@ inline std::string errno_str(int err_num) ...@@ -356,5 +358,3 @@ inline std::string errno_str(int err_num)
} //os } //os
} //details } //details
} //spdlog } //spdlog
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <spdlog/sinks/stdout_sinks.h> #include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/syslog_sink.h> #include <spdlog/sinks/syslog_sink.h>
#include <spdlog/sinks/ansicolor_sink.h> #include <spdlog/sinks/ansicolor_sink.h>
#include <spdlog/sinks/android_sink.h>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
...@@ -104,6 +105,13 @@ inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& ...@@ -104,6 +105,13 @@ inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string&
} }
#endif #endif
#if defined(__ANDROID__)
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag)
{
return create<spdlog::sinks::android_sink>(logger_name, tag);
}
#endif
// Create and register a logger a single sink // Create and register a logger a single sink
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink) inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink)
{ {
......
...@@ -7,51 +7,42 @@ ...@@ -7,51 +7,42 @@
#if defined(__ANDROID__) #if defined(__ANDROID__)
#include <spdlog/sinks/base_sink.h> #include <spdlog/sinks/sink.h>
#include <spdlog/details/null_mutex.h>
#include <android/log.h>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <android/log.h>
namespace spdlog namespace spdlog
{ {
namespace sinks namespace sinks
{ {
/* /*
* Android sink (logging using __android_log_write) * Android sink (logging using __android_log_write)
* __android_log_write is thread-safe. No lock is needed.
*/ */
template<class Mutex> class android_sink : public sink
class base_android_sink : public base_sink < Mutex >
{ {
public: public:
explicit base_android_sink(std::string tag="spdlog"): _tag(tag) explicit android_sink(const std::string& tag = "spdlog"): _tag(tag) {}
{
}
void flush() override void log(const details::log_msg& msg) override
{
}
protected:
void _sink_it(const details::log_msg& msg) override
{ {
const android_LogPriority priority = convert_to_android(msg.level); const android_LogPriority priority = convert_to_android(msg.level);
const int expected_size = msg.formatted.size(); // See system/core/liblog/logger_write.c for explanation of return value
const int size = __android_log_write( const int ret = __android_log_write(
priority, _tag.c_str(), msg.formatted.c_str() priority, _tag.c_str(), msg.formatted.c_str()
); );
if (size > expected_size) if (ret < 0) {
{ throw spdlog_ex("__android_log_write() failed", ret);
// Will write a little bit more than original message
}
else
{
throw spdlog_ex("Send to Android logcat failed");
} }
} }
void flush() override
{
}
private: private:
static android_LogPriority convert_to_android(spdlog::level::level_enum level) static android_LogPriority convert_to_android(spdlog::level::level_enum level)
{ {
...@@ -63,29 +54,20 @@ private: ...@@ -63,29 +54,20 @@ private:
return ANDROID_LOG_DEBUG; return ANDROID_LOG_DEBUG;
case spdlog::level::info: case spdlog::level::info:
return ANDROID_LOG_INFO; return ANDROID_LOG_INFO;
case spdlog::level::notice:
return ANDROID_LOG_INFO;
case spdlog::level::warn: case spdlog::level::warn:
return ANDROID_LOG_WARN; return ANDROID_LOG_WARN;
case spdlog::level::err: case spdlog::level::err:
return ANDROID_LOG_ERROR; return ANDROID_LOG_ERROR;
case spdlog::level::critical: case spdlog::level::critical:
return ANDROID_LOG_FATAL; return ANDROID_LOG_FATAL;
case spdlog::level::alert:
return ANDROID_LOG_FATAL;
case spdlog::level::emerg:
return ANDROID_LOG_FATAL;
default: default:
throw spdlog_ex("Incorrect level value"); return ANDROID_LOG_DEFAULT;
} }
} }
std::string _tag; std::string _tag;
}; };
typedef base_android_sink<std::mutex> android_sink_mt;
typedef base_android_sink<details::null_mutex> android_sink_st;
} }
} }
......
...@@ -101,6 +101,9 @@ std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool co ...@@ -101,6 +101,9 @@ std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool co
std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0); std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0);
#endif #endif
#if defined(__ANDROID__)
std::shared_ptr<logger> android_logger(const std::string& logger_name, const std::string& tag = "spdlog");
#endif
// Create and register a logger a single sink // Create and register a logger a single sink
std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink); std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment