Skip to content

Commit

Permalink
Update NDK 25 LTS (r25b) (#7240)
Browse files Browse the repository at this point in the history
* fix script

* initial paths fixes

* use lld ref

* keep NDKs make file

* mk for libunwind fixes

* draft implementation of the unwinder using `_Unwind_Backtrace` and `_Unwind_GetIP`

* add `_Unwind_Backtrace` + `_Unwind_GetIP` implementation of the stack unwinding

* build luajit with ndk 25

* rebuild bullet for android

* rebuild protobuf for android

* Revert "draft implementation of the unwinder using `_Unwind_Backtrace` and `_Unwind_GetIP`"

This reverts commit e790b25.

* fix LD arguments for protobuf on Android

* fix extender constants

* make sure this dmSDK uses NDK25b first

* don't need to link STL manually anymore

* use llvm-ar tools instead of GCC `ar`

* fix build_input for ndk25

* use NDK25 instead of NDK25b for enviroment variables

* use libunwind_ndk name
  • Loading branch information
AGulev committed Jan 16, 2023
1 parent ea03490 commit a9d41b8
Show file tree
Hide file tree
Showing 27 changed files with 286 additions and 183 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Expand Up @@ -5,6 +5,9 @@
.lock-waf*
/share/ext/build
/share/ext/download
/share/ext/tremolo/tmp/
/share/ext/protobuf/tmp/
/share/ext/protobuf/cross_tmp/
/share/extender/build
/go/pkg
/go/bin
Expand Down Expand Up @@ -50,3 +53,7 @@ external/**/build/
editor/resources/splash.css
editor/.calva/output-window/output.calva-repl
editor/.lsp/sqlite.db

#build_external
/packages/bullet-2.77/
/packages/lib/
2 changes: 1 addition & 1 deletion build_tools/sdk.py
Expand Up @@ -58,7 +58,7 @@
## **********************************************************************************************
# Android

ANDROID_NDK_VERSION='20'
ANDROID_NDK_VERSION='25b'

## **********************************************************************************************
# Win32
Expand Down
17 changes: 6 additions & 11 deletions build_tools/waf_dynamo.py
Expand Up @@ -81,11 +81,10 @@ def transform_runnable_path(platform, path):

ANDROID_ROOT=SDK_ROOT
ANDROID_BUILD_TOOLS_VERSION = '32.0.0'
ANDROID_NDK_API_VERSION='16' # Android 4.1
ANDROID_NDK_API_VERSION='19' # Android 4.4
ANDROID_NDK_ROOT=os.path.join(SDK_ROOT,'android-ndk-r%s' % sdk.ANDROID_NDK_VERSION)
ANDROID_TARGET_API_LEVEL='31' # Android 12.0
ANDROID_MIN_API_LEVEL='16'
ANDROID_GCC_VERSION='4.9'
ANDROID_MIN_API_LEVEL='19'
ANDROID_64_NDK_API_VERSION='21' # Android 5.0
EMSCRIPTEN_ROOT=os.environ.get('EMSCRIPTEN', '')

Expand Down Expand Up @@ -246,9 +245,6 @@ def getAndroidNDKArch(target_arch):
def getAndroidArch(target_arch):
return 'arm64-v8a' if 'arm64' == target_arch else 'armeabi-v7a'

def getAndroidBuildtoolName(target_arch):
return 'aarch64-linux-android' if 'arm64' == target_arch else 'arm-linux-androideabi'

def getAndroidCompilerName(target_arch, api_version):
if target_arch == 'arm64':
return 'aarch64-linux-android%s-clang' % (api_version)
Expand Down Expand Up @@ -872,8 +868,7 @@ def _strip_executable(bld, platform, target_arch, path):
if 'android' in platform:
HOME = os.environ['USERPROFILE' if sys.platform == 'win32' else 'HOME']
ANDROID_HOST = 'linux' if sys.platform == 'linux' else 'darwin'
build_tool = getAndroidBuildtoolName(target_arch)
strip = "%s/toolchains/%s-%s/prebuilt/%s-x86_64/bin/%s-strip" % (ANDROID_NDK_ROOT, build_tool, ANDROID_GCC_VERSION, ANDROID_HOST, build_tool)
strip = "%s/toolchains/llvm/prebuilt/%s-x86_64/bin/llvm-strip" % (ANDROID_NDK_ROOT, ANDROID_HOST)

return bld.exec_command("%s %s" % (strip, path))

Expand Down Expand Up @@ -1517,7 +1512,7 @@ def detect(conf):
conf.env['CPP'] = '%s/clang -E' % bin_dir
conf.env['AR'] = '%s/ar' % bin_dir
conf.env['RANLIB'] = '%s/ranlib' % bin_dir
conf.env['LD'] = '%s/ld' % bin_dir
conf.env['LD'] = '%s/lld' % bin_dir

conf.env['GCC-OBJCXX'] = '-xobjective-c++'
conf.env['GCC-OBJCLINK'] = '-lobjc'
Expand All @@ -1529,18 +1524,18 @@ def detect(conf):
if bp_os == 'macos':
bp_os = 'darwin' # the toolset is still called darwin
target_arch = build_util.get_target_architecture()
tool_name = getAndroidBuildtoolName(target_arch)
api_version = getAndroidNDKAPIVersion(target_arch)
clang_name = getAndroidCompilerName(target_arch, api_version)
bintools = '%s/toolchains/llvm/prebuilt/%s-%s/bin' % (ANDROID_NDK_ROOT, bp_os, bp_arch)
tool_name = "llvm"

conf.env['CC'] = '%s/%s' % (bintools, clang_name)
conf.env['CXX'] = '%s/%s++' % (bintools, clang_name)
conf.env['LINK_CXX'] = '%s/%s++' % (bintools, clang_name)
conf.env['CPP'] = '%s/%s -E' % (bintools, clang_name)
conf.env['AR'] = '%s/%s-ar' % (bintools, tool_name)
conf.env['RANLIB'] = '%s/%s-ranlib' % (bintools, tool_name)
conf.env['LD'] = '%s/%s-ld' % (bintools, tool_name)
conf.env['LD'] = '%s/lld' % (bintools)
conf.env['DX'] = '%s/android-sdk/build-tools/%s/dx' % (ANDROID_ROOT, ANDROID_BUILD_TOOLS_VERSION)

elif 'linux' == build_util.get_target_os():
Expand Down
58 changes: 4 additions & 54 deletions build_tools/waf_package.py
Expand Up @@ -13,20 +13,15 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.



import os
import glob
import run
import Constants
import Environment
import Node
import Utils
from waflib import ConfigSet
from waflib import Build

def load_build_context(directory):
cachedir = os.path.join(directory,Constants.CACHE_DIR)
return Environment.Environment(os.path.join(cachedir,'default.cache.py'))

cachedir = os.path.join(directory,Build.CACHE_DIR)
return ConfigSet.ConfigSet(os.path.join(cachedir,'_cache.py'))

def glob_files(patterns, cwd=None):
oldcwd=os.getcwd()
Expand All @@ -41,51 +36,6 @@ def glob_files(patterns, cwd=None):
os.chdir(oldcwd)
return out

# Original from wafadmin/Build.py install_files:
# I couldn't get the original code to work as I needed, so I made a small change to it.
def package_install_files(self, path, files, env=None, chmod=Constants.O644, relative_trick=False, cwd=None):
if env:
assert isinstance(env,Environment.Environment),"invalid parameter"
else:
env=self.env
if not path:return[]
if not cwd:
cwd=self.path
if isinstance(files,str)and'*'in files:
gl=cwd.abspath()+os.sep+files
lst=glob.glob(gl)
else:
lst=Utils.to_list(files)
destpath=self.get_install_path(path,env)
Utils.check_dir(destpath)
installed_files=[]
for filename in lst:
if isinstance(filename,str)and os.path.isabs(filename):
alst=Utils.split_path(filename)
destfile=os.path.join(destpath,alst[-1])
else:
if isinstance(filename,Node.Node):
nd=filename
else:
# DEFOLD: This is the fix to make the relative paths work our way
fullpath=os.path.join(self.path.abspath(),filename)
filename=os.path.relpath(fullpath,cwd.abspath())
# DEFOLD: <- end fix
nd=cwd.find_resource(filename)
if not nd:
raise Utils.WafError("Unable to install the file %r (not found in %s)"%(filename,cwd))
if relative_trick:
destfile=os.path.join(destpath,filename)
Utils.check_dir(os.path.dirname(destfile))
else:
destfile=os.path.join(destpath,nd.name)
filename=nd.abspath(env)
if self.do_install(filename,destfile,chmod):
installed_files.append(destfile)
return installed_files


def create_tar(files, cwd, target):
cmd = 'tar zcf %s %s' % (target, ' '.join(files))
run.command(cmd.split(), cwd=cwd)

2 changes: 1 addition & 1 deletion editor/resources/meta.edn
Expand Up @@ -642,7 +642,7 @@
:path ["android" "version_code"]}
{:type :integer,
:help "minimum API Level required for the application to run (android:minSdkVersion)",
:default 16,
:default 19,
:path ["android" "minimum_sdk_version"]}
{:type :integer,
:help "the API Level that the application targets (android:targetSdkVersion)",
Expand Down
172 changes: 172 additions & 0 deletions engine/crash/src/backtrace_libunwind_ndk.cpp
@@ -0,0 +1,172 @@
// Copyright 2020-2022 The Defold Foundation
// Copyright 2014-2020 King
// Copyright 2009-2014 Ragnar Svensson, Christian Murray
// Licensed under the Defold License version 1.0 (the "License"); you may not use
// this file except in compliance with the License.
//
// You may obtain a copy of the License, together with FAQs at
// https://www.defold.com/license
//
// 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.

#include <assert.h>
#include <dlib/log.h>
#include <dlib/dlib.h>
#include <signal.h>
#include <stdio.h>
#include <unwind.h>
#include <dlfcn.h>
#include "crash.h"
#include "crash_private.h"

namespace dmCrash
{
static const int SIGNAL_MAX = 64;

static bool g_CrashDumpEnabled = true;
static FCallstackExtraInfoCallback g_CrashExtraInfoCallback = 0;
static void* g_CrashExtraInfoCallbackCtx = 0;

struct unwind_data {
uint32_t offset_extra;
uint32_t stack_index;
};

void EnableHandler(bool enable)
{
g_CrashDumpEnabled = enable;
}

void HandlerSetExtraInfoCallback(FCallstackExtraInfoCallback cbk, void* ctx)
{
g_CrashExtraInfoCallback = cbk;
g_CrashExtraInfoCallbackCtx = ctx;
}

_Unwind_Reason_Code OnFrameEnter(struct _Unwind_Context *context, void *data)
{
unwind_data * unwindData = (unwind_data *) data;
const uintptr_t pc = _Unwind_GetIP(context);
if (pc)
{
g_AppState.m_Ptr[g_AppState.m_PtrCount] = (void*)(uintptr_t)pc;
g_AppState.m_PtrCount++;
Dl_info dl_info;
int result = dladdr((void *) pc, &dl_info);
if (result) {
const char* proc_path = dl_info.dli_fname;
bool proc_path_truncated = false;
if (proc_path) {
int proc_path_len = strlen(proc_path);
if (proc_path_len > 32) {
proc_path = proc_path + (proc_path_len-32);
proc_path_truncated = true;
}
}
char extra[256];
snprintf(extra, sizeof(extra),
"#%02d pc %012p %s%s %s+%u",
unwindData->stack_index++,
(void*)((uintptr_t)pc - (intptr_t) dl_info.dli_fbase),
proc_path_truncated ? "..." : "",
proc_path ? proc_path : "",
dl_info.dli_sname ? dl_info.dli_sname : "<unknown>",
dl_info.dli_saddr != NULL ? (void*)((intptr_t) pc - (intptr_t) dl_info.dli_saddr) : 0);

int extra_len = strlen(extra);
if ((unwindData->offset_extra + extra_len) < (dmCrash::AppState::EXTRA_MAX - 1))
{
memcpy(g_AppState.m_Extra + unwindData->offset_extra, extra, extra_len);
g_AppState.m_Extra[unwindData->offset_extra + extra_len] = '\n';
unwindData->offset_extra += extra_len + 1;
}
else
{
dmLogWarning("Not enough space to write entire stacktrace!");
}
}
}
return g_AppState.m_PtrCount >= AppState::PTRS_MAX ? _URC_END_OF_STACK : _URC_NO_REASON;
}

static void ResetToDefaultHandler(const int signum)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
sigaction(signum, &sa, NULL);
}

static void Handler(const int signo, siginfo_t* const si, void *const sc)
{
if (!g_CrashDumpEnabled)
return;

g_AppState.m_Signum = signo;
g_AppState.m_PtrCount = 0;

// The default behavior is restored for the signal.
// Unless this is done first thing in the signal handler we'll
// be stuck in a signal-handler loop forever.
ResetToDefaultHandler(signo);

unwind_data unwindData;
unwindData.offset_extra = 0;
unwindData.stack_index = 0;
_Unwind_Backtrace(OnFrameEnter, &unwindData);

if (g_CrashExtraInfoCallback)
{
int extra_len = strlen(g_AppState.m_Extra);
g_CrashExtraInfoCallback(g_CrashExtraInfoCallbackCtx, g_AppState.m_Extra + extra_len, dmCrash::AppState::EXTRA_MAX - extra_len - 1);
}

WriteCrash(g_FilePath, &g_AppState);

bool is_debug_mode = dLib::IsDebugMode();
dLib::SetDebugMode(true);
dmLogError("CALL STACK:\n\n%s\n", g_AppState.m_Extra);
dLib::SetDebugMode(is_debug_mode);
}

void WriteDump()
{
siginfo_t empty;
Handler(0xDEAD, &empty, 0);
}

void InstallOnSignal(int signum)
{
assert(signum >= 0 && signum < SIGNAL_MAX);

struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = Handler;
sa.sa_flags = SA_SIGINFO;

sigaction(signum, &sa, NULL);
}

void SetCrashFilename(const char*)
{
}

void PlatformPurge()
{
}

void InstallHandler()
{
InstallOnSignal(SIGSEGV);
InstallOnSignal(SIGBUS);
InstallOnSignal(SIGTRAP);
InstallOnSignal(SIGILL);
InstallOnSignal(SIGABRT);
}
}
2 changes: 1 addition & 1 deletion engine/crash/src/wscript
Expand Up @@ -20,7 +20,7 @@ def build(bld):
target = 'crashext_null')

if 'android' in bld.env['PLATFORM']:
sig_handler = 'backtrace_libunwind.cpp'
sig_handler = 'backtrace_libunwind_ndk.cpp'
load_addrs = 'load_addrs_proc_smap.cpp'
file_handler = 'file_posix.cpp'
elif 'linux' in bld.env['PLATFORM']:
Expand Down

0 comments on commit a9d41b8

Please sign in to comment.