Merge pull request #277 from hghwng/master

Fix compilation on Android.
This commit is contained in:
Gabi Melman 2016-09-14 17:55:43 +03:00 committed by GitHub
commit 87d79eb95d
9 changed files with 65 additions and 41 deletions

3
.gitignore vendored
View File

@ -1,4 +1,4 @@
# Auto generated files # Auto generated files
*.slo *.slo
*.lo *.lo
*.o *.o
@ -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

View File

@ -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*[])
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*[])
// 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()
#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()
}); });
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3); spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
} }

15
example/jni/Android.mk Normal file
View File

@ -0,0 +1,15 @@
# 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)

View File

@ -0,0 +1,2 @@
# Exceptions are used in spdlog. Link to an exception-ready C++ runtime.
APP_STL = gnustl_static

1
example/jni/example.cpp Symbolic link
View File

@ -0,0 +1 @@
../example.cpp

View File

@ -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)
} //os } //os
} //details } //details
} //spdlog } //spdlog

View File

@ -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&
} }
#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)
{ {

View File

@ -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 log(const details::log_msg& msg) override
{ {
const android_LogPriority priority = convert_to_android(msg.level);
// See system/core/liblog/logger_write.c for explanation of return value
const int ret = __android_log_write(
priority, _tag.c_str(), msg.formatted.c_str()
);
if (ret < 0) {
throw spdlog_ex("__android_log_write() failed", ret);
}
} }
void flush() override void flush() override
{ {
} }
protected:
void _sink_it(const details::log_msg& msg) override
{
const android_LogPriority priority = convert_to_android(msg.level);
const int expected_size = msg.formatted.size();
const int size = __android_log_write(
priority, _tag.c_str(), msg.formatted.c_str()
);
if (size > expected_size)
{
// Will write a little bit more than original message
}
else
{
throw spdlog_ex("Send to Android logcat failed");
}
}
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:
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;
} }
} }

View File

@ -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);