From 11843fd10ebb4f4fa670ee635b7a8a5d4d7d2cfc Mon Sep 17 00:00:00 2001 From: Chris Hopman Date: Tue, 23 Feb 2016 20:05:46 -0800 Subject: [PATCH] Initialize glog in react native. Reviewed By: mhorowitz Differential Revision: D2967180 fb-gh-sync-id: fe59b7f7c7dab8b5e7f3a449e72b467e1c2c2c67 shipit-source-id: fe59b7f7c7dab8b5e7f3a449e72b467e1c2c2c67 --- ReactAndroid/DEFS | 5 +- .../jni/first-party/fbgloginit/Android.mk | 24 +++ .../src/main/jni/first-party/fbgloginit/BUCK | 20 +++ .../jni/first-party/fbgloginit/fb/glog_init.h | 11 ++ .../jni/first-party/fbgloginit/glog_init.cpp | 142 ++++++++++++++++++ .../src/main/jni/react/jni/Android.mk | 3 +- ReactAndroid/src/main/jni/react/jni/BUCK | 1 + .../src/main/jni/react/jni/OnLoad.cpp | 2 + 8 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp diff --git a/ReactAndroid/DEFS b/ReactAndroid/DEFS index f9f43995e..104c16189 100644 --- a/ReactAndroid/DEFS +++ b/ReactAndroid/DEFS @@ -6,7 +6,6 @@ import os - # Example: react_native_target('java/com/facebook/react/common:common') def react_native_target(path): return '//ReactAndroid/src/main/' + path @@ -34,6 +33,8 @@ JSC_INTERNAL_DEPS = [ '//native/third-party/jsc-internal:jsc_legacy_profiler', ] +FBGLOGINIT_TARGET = '//ReactAndroid/src/main/jni/first-party/fbgloginit:fbgloginit' + INTERNAL_APP = 'PUBLIC' # React property preprocessor @@ -96,4 +97,4 @@ def robolectric3_test(name, deps, vm_args=None, *args, **kwargs): vm_args=vm_args + extra_vm_args, *args, **kwargs - ) \ No newline at end of file + ) diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk b/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk new file mode 100644 index 000000000..6d08079a7 --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + glog_init.cpp + +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_CFLAGS := -fexceptions -fno-omit-frame-pointer +LOCAL_CFLAGS += -Wall -Werror + +CXX11_FLAGS := -std=gnu++11 +LOCAL_CFLAGS += $(CXX11_FLAGS) + +LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS) + +LOCAL_LDLIBS := -llog + +LOCAL_SHARED_LIBRARIES := libglog + +LOCAL_MODULE := libglog_init + +include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK new file mode 100644 index 000000000..18ff2fbb4 --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK @@ -0,0 +1,20 @@ +cxx_library( + name = 'fbgloginit', + force_static = True, + srcs = [ + 'glog_init.cpp', + ], + exported_headers = ['fb/glog_init.h'], + compiler_flags = [ + '-fexceptions', + '-fno-omit-frame-pointer', + ], + linker_flags = [ + '-llog', + ], + deps=[ + '//xplat/third-party/glog:glog', + ], + visibility=['PUBLIC'], +) + diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h b/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h new file mode 100644 index 000000000..311f70350 --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h @@ -0,0 +1,11 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include + +namespace facebook { namespace gloginit { + +void initialize(const char* tag = "ReactNativeJNI"); + +}} diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp b/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp new file mode 100644 index 000000000..771516a2d --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp @@ -0,0 +1,142 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "fb/glog_init.h" + +#include +#include +#include + +#include + +#ifdef __ANDROID__ + +#include + +static int toAndroidLevel(google::LogSeverity severity) { + switch (severity) { + case google::GLOG_INFO: + return ANDROID_LOG_INFO; + case google::GLOG_WARNING: + return ANDROID_LOG_WARN; + case google::GLOG_ERROR: + return ANDROID_LOG_ERROR; + case google::GLOG_FATAL: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_FATAL; + } +} + +/** + * Sends GLog output to adb logcat. + */ +class LogcatSink : public google::LogSink { + public: + void send( + google::LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const struct ::tm* tm_time, + const char* message, + size_t message_len) override { + auto level = toAndroidLevel(severity); + __android_log_print( + level, + base_filename, + "%.*s", + (int)message_len, + message); + } +}; + +/** + * Sends GLog output to adb logcat. + */ +class TaggedLogcatSink : public google::LogSink { + const std::string tag_; + + public: + TaggedLogcatSink(const std::string &tag) : tag_{tag} {} + + void send( + google::LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const struct ::tm* tm_time, + const char* message, + size_t message_len) override { + auto level = toAndroidLevel(severity); + __android_log_print( + level, + tag_.c_str(), + "%.*s", + (int)message_len, + message); + } +}; + +static google::LogSink* make_sink(const std::string& tag) { + if (tag.empty()) { + return new LogcatSink{}; + } else { + return new TaggedLogcatSink{tag}; + } +} + +static void sendGlogOutputToLogcat(const char* tag) { + google::AddLogSink(make_sink(tag)); + + // Disable logging to files + for (auto i = 0; i < google::NUM_SEVERITIES; ++i) { + google::SetLogDestination(i, ""); + } +} + +#endif // __ANDROID__ + +static void lastResort(const char* tag, const char* msg, const char* arg = nullptr) { +#ifdef __ANDROID__ + if (!arg) { + __android_log_write(ANDROID_LOG_ERROR, tag, msg); + } else { + __android_log_print(ANDROID_LOG_ERROR, tag, "%s: %s", msg, arg); + } +#else + std::cerr << msg; + if (arg) { + std::cerr << ": " << arg; + } + std::cerr << std::endl; +#endif +} + +namespace facebook { namespace gloginit { + +void initialize(const char* tag) { + static std::once_flag flag{}; + static auto failed = false; + + std::call_once(flag, [tag] { + try { + google::InitGoogleLogging(tag); + +#ifdef __ANDROID__ + sendGlogOutputToLogcat(tag); +#endif + } catch (std::exception& ex) { + lastResort(tag, "Failed to initialize glog", ex.what()); + failed = true; + } catch (...) { + lastResort(tag, "Failed to initialize glog"); + failed = true; + } + }); + + if (failed) { + throw std::runtime_error{"Failed to initialize glog"}; + } +} + +}} diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index 9d4d9b2b5..e5184d8e8 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_CFLAGS += $(CXX11_FLAGS) LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS) LOCAL_LDLIBS += -landroid -LOCAL_SHARED_LIBRARIES := libfolly_json libfbjni libjsc +LOCAL_SHARED_LIBRARIES := libfolly_json libfbjni libjsc libglog_init LOCAL_STATIC_LIBRARIES := libreactnative include $(BUILD_SHARED_LIBRARY) @@ -30,5 +30,6 @@ include $(BUILD_SHARED_LIBRARY) $(call import-module,react) $(call import-module,jsc) $(call import-module,folly) +$(call import-module,fbgloginit) $(call import-module,jni) $(call import-module,jsc) diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index bebdf54ce..830a38e0c 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -4,6 +4,7 @@ include_defs('//ReactAndroid/DEFS') SUPPORTED_PLATFORMS = '^android-(armv7|x86)$' DEPS = [ + FBGLOGINIT_TARGET, '//native/jni:jni', '//native/third-party/android-ndk:android', '//xplat/folly:molly', diff --git a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp index 1a4dbe3c1..0cb6f5bc1 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -845,6 +846,7 @@ jmethodID getLogMarkerMethod() { extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { return initialize(vm, [] { + facebook::gloginit::initialize(); // Inject some behavior into react/ ReactMarker::logMarker = bridge::logMarker; WebWorkerUtil::createWebWorkerThread = WebWorkers::createWebWorkerThread;