Skip to content

Commit

Permalink
Dev: add patch for Crashlytics and build-id linker flag
Browse files Browse the repository at this point in the history
  • Loading branch information
andriydruk committed Nov 30, 2024
1 parent 494884a commit 82b500c
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 4 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build-android-toolchain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ jobs:
~/icu/build-armv7a-linux-androideabi/lib
~/icu/build-x86_64-linux-android/lib
~/icu/build-i686-linux-android/lib
key: icu-73-2-r4
key: icu-73-2-r5
- name: Install dependencies
if: steps.cache-icu.outputs.cache-hit != 'true'
run: ./build/Linux/000-install-dependencies.sh
Expand Down Expand Up @@ -260,7 +260,7 @@ jobs:
~/curl/arm
~/curl/x86_64
~/curl/x86
key: curl-7_88_1-r9
key: curl-7_88_1-r10
- name: Install dependencies
if: steps.cache-curl.outputs.cache-hit != 'true'
run: ./build/Linux/000-install-dependencies.sh
Expand Down Expand Up @@ -326,7 +326,7 @@ jobs:
~/libxml/arm
~/libxml/x86_64
~/libxml/x86
key: libxmlv2.9.14-r4
key: libxmlv2.9.14-r5
- name: Install dependencies
if: steps.cache-libxml.outputs.cache-hit != 'true'
run: ./build/Linux/000-install-dependencies.sh
Expand Down
1 change: 1 addition & 0 deletions build/Linux/040-build-icu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pushd $ICU_LIBS

export CFLAGS="-O3 -g -DNDEBUG -fpic -ffunction-sections -fdata-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes"
export CXXFLAGS="-fexceptions -frtti -O3 -g -DNDEBUG -fpic -ffunction-sections -fdata-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes"
export LDFLAGS="$LDFLAGS -Wl,--build-id=sha1"

targets=(armv7a-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android)
for target in ${targets[*]}
Expand Down
1 change: 1 addition & 0 deletions build/Linux/042-build-curl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ HOST=linux-x86_64
TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST

export CFLAGS="-O3 -g -DNDEBUG -fpic -ffunction-sections -fdata-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes"
export LDFLAGS="$LDFLAGS -Wl,--build-id=sha1"

for arch in ${archs[*]}
do
Expand Down
1 change: 1 addition & 0 deletions build/Linux/043-build-libxml.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ HOST=linux-x86_64
TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST

export CFLAGS="-O3 -g -DNDEBUG -fno-semantic-interposition -fpic -ffunction-sections -fdata-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes"
export LDFLAGS="$LDFLAGS -Wl,--build-id=sha1"

for arch in ${archs[*]}
do
Expand Down
5 changes: 4 additions & 1 deletion build/Linux/common-flags.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
set(CMAKE_TOOLCHAIN_FILE "$ENV{ANDROID_NDK}/build/cmake/android.toolchain.cmake" CACHE STRING "")

include($ENV{ANDROID_NDK}/build/cmake/flags.cmake)

set(CMAKE_Swift_SDK "$ENV{DST_ROOT}/swift-nightly-install" CACHE STRING "")
set(CMAKE_Swift_COMPILER "$ENV{DST_ROOT}/swift-nightly-install/usr/bin/swiftc" CACHE STRING "")

Expand All @@ -11,5 +13,6 @@ set(ANDROID_NATIVE_API_LEVEL "24" CACHE STRING "")
set(CMAKE_Swift_FLAGS
"-tools-directory $ENV{ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin \
-sdk $ENV{ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot \
-resource-dir ${CMAKE_Swift_SDK}/usr/lib/swift"
-resource-dir ${CMAKE_Swift_SDK}/usr/lib/swift \
-Xlinker --build-id=sha1"
CACHE STRING "")
271 changes: 271 additions & 0 deletions patches/release/5.7/swift/0008-Enable-crashlytics-and-build-ids.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake
index ddfcd7e3e54..fac2247c5e9 100644
--- a/stdlib/cmake/modules/AddSwiftStdlib.cmake
+++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake
@@ -2447,6 +2447,8 @@ function(add_swift_target_library name)
list(APPEND swiftlib_link_flags_all "-shared")
# TODO: Instead of `lib${name}.so` find variable or target property which already have this value.
list(APPEND swiftlib_link_flags_all "-Wl,-soname,lib${name}.so")
+ # Add the build-id flag to ensure a unique identifier is included in the output binary.
+ list(APPEND swiftlib_link_flags_all "-Wl,--build-id")
endif()

if (SWIFTLIB_BACK_DEPLOYMENT_LIBRARY)
diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp
index 26e3a01998c..a53a3251c48 100644
--- a/stdlib/public/runtime/Errors.cpp
+++ b/stdlib/public/runtime/Errors.cpp
@@ -55,6 +55,10 @@
#include <asl.h>
#elif defined(__ANDROID__)
#include <android/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+#include "crashlytics.h"
+#pragma clang diagnostic pop
#endif

#if defined(__ELF__)
@@ -315,6 +319,8 @@ reportOnCrash(uint32_t flags, const char *message)
&oldMessage, newMessage,
std::memory_order_release,
SWIFT_MEMORY_ORDER_CONSUME));
+#elif defined(__ANDROID__)
+ firebase::crashlytics::Log(message);
#else
// empty
#endif // SWIFT_HAVE_CRASHREPORTERCLIENT
diff --git a/stdlib/public/runtime/crashlytics.h b/stdlib/public/runtime/crashlytics.h
new file mode 100644
index 00000000000..2571080a28a
--- /dev/null
+++ b/stdlib/public/runtime/crashlytics.h
@@ -0,0 +1,227 @@
+// Copyright 2020 Google LLC
+//
+// 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
+//
+// http://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.
+#ifndef __CRASHLYTICS_H__
+#define __CRASHLYTICS_H__
+
+#include <cstddef>
+#include <string>
+#include <memory>
+#include <functional>
+#include <dlfcn.h>
+
+/// @brief Firebase Crashlytics NDK API, for Android apps which use native code.
+///
+/// This API is optional: It enables adding custom metadata to your native Crashlytics crash
+/// reports. See <a href="https://firebase.google.com/docs/crashlytics">the developer guides</a>
+/// for information on using Firebase Crashlytics in your NDK-enabled Android apps.
+namespace firebase { namespace crashlytics {
+
+/** PUBLIC API **/
+
+/// @brief Initialize the Crashlytics NDK API, for Android apps using native code.
+///
+/// This allows finer grained control of when the native API is initialized. Calling this
+/// function is not not strictly necessary as the API will be initialized on the first call
+/// to any of the functions within the firebase::crashlytics namespace.
+///
+/// This call is only required for adding custom metadata to crash reports. Use of
+/// this header file is NOT required for Android NDK crash reporting.
+inline bool Initialize();
+
+/// Deprecated; now a no-op and does not need to be called.
+inline void Terminate();
+
+/// @brief Logs a message to be included in the next fatal or non-fatal report.
+inline void Log(const char* msg);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, bool value);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, const char *value);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, double value);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, float value);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, int value);
+
+/// @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetCustomKey(const char* key, long value);
+
+/// @brief Records a user ID (identifier) that's associated with subsequent fatal and non-fatal
+/// reports.
+inline void SetUserId(const char* id);
+
+/** END PUBLIC API **/
+
+namespace detail {
+
+struct __crashlytics_context;
+struct __crashlytics_unspecified;
+typedef struct __crashlytics_context __crashlytics_context_t;
+typedef struct __crashlytics_unspecified __crashlytics_unspecified_t;
+
+typedef __crashlytics_unspecified_t* (*__crashlytics_initialize_t) ();
+typedef void (*__crashlytics_set_internal_t) (__crashlytics_unspecified_t *, const char *, const char *);
+typedef void (*__crashlytics_log_internal_t) (__crashlytics_unspecified_t *, const char *);
+typedef void (*__crashlytics_set_user_id_internal_t) (__crashlytics_unspecified_t *, const char *);
+typedef void (*__crashlytics_dispose_t) (__crashlytics_unspecified_t *);
+
+struct __crashlytics_context {
+ __crashlytics_set_internal_t __set;
+ __crashlytics_log_internal_t __log;
+ __crashlytics_set_user_id_internal_t __set_user_id;
+
+ __crashlytics_unspecified_t* __ctx;
+ __crashlytics_dispose_t __dispose;
+};
+
+#define __CRASHLYTICS_NULL_CONTEXT (struct __crashlytics_context *) 0
+#define __CRASHLYTICS_INITIALIZE_FAILURE (struct __crashlytics_unspecified *) 0
+#define __CRASHLYTICS_DECORATED __attribute__ ((always_inline))
+
+inline const __crashlytics_context_t* __crashlytics_context() __CRASHLYTICS_DECORATED;
+inline __crashlytics_context_t* __crashlytics_init() __CRASHLYTICS_DECORATED;
+
+inline void invoke(const std::function<void (const __crashlytics_context_t *)>& func) __CRASHLYTICS_DECORATED;
+
+} // end namespace detail
+
+inline bool Initialize() {
+ return detail::__crashlytics_context() != nullptr;
+}
+
+inline void Terminate() {
+ // no-op
+}
+
+inline void Log(const char* msg) {
+ detail::invoke([&](const detail::__crashlytics_context_t* context) {
+ context->__log(context->__ctx, msg);
+ });
+}
+
+inline void SetCustomKey(const char* key, const char* value) {
+ detail::invoke([&](const detail::__crashlytics_context_t* context) {
+ context->__set(context->__ctx, key, value);
+ });
+}
+
+inline void SetCustomKey(const char* key, bool value) {
+ SetCustomKey(key, value ? "true" : "false");
+}
+
+inline void SetCustomKey(const char* key, double value) {
+ SetCustomKey(key, std::to_string(value).c_str());
+}
+
+inline void SetCustomKey(const char* key, float value) {
+ SetCustomKey(key, std::to_string(value).c_str());
+}
+
+inline void SetCustomKey(const char* key, int value) {
+ SetCustomKey(key, std::to_string(value).c_str());
+}
+
+inline void SetCustomKey(const char* key, long value) {
+ SetCustomKey(key, std::to_string(value).c_str());
+}
+
+inline void SetUserId(const char* id) {
+ detail::invoke([&](const detail::__crashlytics_context_t* context) {
+ context->__set_user_id(context->__ctx, id);
+ });
+}
+
+namespace detail {
+
+#define __CRASHLYTICS_NULL_ON_NULL(expression) \
+ do { \
+ if (((expression)) == NULL) { \
+ return NULL; \
+ } \
+ } while (0)
+
+inline __crashlytics_context_t* __crashlytics_construct(
+ __crashlytics_unspecified_t* ctx, void* sym_set, void* sym_log, void* sym_dispose, void* sym_set_user_id) __CRASHLYTICS_DECORATED;
+inline __crashlytics_context_t* __crashlytics_construct(
+ __crashlytics_unspecified_t* ctx, void* sym_set, void* sym_log, void* sym_dispose, void* sym_set_user_id) {
+ __crashlytics_context_t* context;
+
+ __CRASHLYTICS_NULL_ON_NULL(context = new __crashlytics_context_t);
+
+ context->__set = (__crashlytics_set_internal_t) sym_set;
+ context->__log = (__crashlytics_log_internal_t) sym_log;
+ context->__set_user_id = (__crashlytics_set_user_id_internal_t) sym_set_user_id;
+ context->__ctx = ctx;
+ context->__dispose = (__crashlytics_dispose_t) sym_dispose;
+
+ return context;
+}
+
+inline const __crashlytics_context_t* __crashlytics_context() {
+ static std::unique_ptr<__crashlytics_context_t> context { __crashlytics_init() };
+ return context.get();
+}
+
+inline __crashlytics_context_t* __crashlytics_init() {
+ void* lib;
+ void* sym_ini;
+ void* sym_log;
+ void* sym_set;
+ void* sym_dispose;
+ void* sym_set_user_id;
+
+ __CRASHLYTICS_NULL_ON_NULL(lib = dlopen("libcrashlytics.so", RTLD_LAZY | RTLD_LOCAL));
+ __CRASHLYTICS_NULL_ON_NULL(sym_ini = dlsym(lib, "external_api_initialize"));
+ __CRASHLYTICS_NULL_ON_NULL(sym_set = dlsym(lib, "external_api_set"));
+ __CRASHLYTICS_NULL_ON_NULL(sym_log = dlsym(lib, "external_api_log"));
+ __CRASHLYTICS_NULL_ON_NULL(sym_dispose = dlsym(lib, "external_api_dispose"));
+ __CRASHLYTICS_NULL_ON_NULL(sym_set_user_id = dlsym(lib, "external_api_set_user_id"));
+
+ __crashlytics_unspecified_t* ctx = ((__crashlytics_initialize_t) sym_ini)();
+
+ return ctx == __CRASHLYTICS_INITIALIZE_FAILURE
+ ? __CRASHLYTICS_NULL_CONTEXT
+ : __crashlytics_construct(
+ ctx,
+ sym_set,
+ sym_log,
+ sym_dispose,
+ sym_set_user_id
+ );
+}
+
+inline void invoke(const std::function<void (const __crashlytics_context_t *)>& func) {
+ const __crashlytics_context_t* context = __crashlytics_context();
+ if (context != nullptr) {
+ func(context);
+ }
+}
+
+} // end namespace detail
+
+}} // end namespace firebase::crashlytics
+
+#endif /* __CRASHLYTICS_H__ */
\ No newline at end of file

0 comments on commit 82b500c

Please sign in to comment.