summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.gypi8
-rwxr-xr-xconfigure.py16
-rw-r--r--deps/cares/config/android/ares_config.h2
-rw-r--r--deps/openssl/openssl-cl_no_asm.gypi2
-rw-r--r--deps/openssl/openssl_no_asm.gypi2
-rw-r--r--deps/uvwasi/src/uvwasi.c18
-rw-r--r--deps/v8/DEPS1
-rwxr-xr-xdeps/v8/tools/node/fetch_deps.py1
-rw-r--r--lib/akono.js69
-rw-r--r--node.gyp2
-rw-r--r--node.gypi45
-rw-r--r--taler-android-build/.gitignore1
-rw-r--r--taler-android-build/README1
-rwxr-xr-xtaler-android-build/arm62
-rwxr-xr-xtaler-android-build/arm6461
-rwxr-xr-xtaler-android-build/build-android-node25
-rwxr-xr-xtaler-android-build/build-android-v852
-rwxr-xr-xtaler-android-build/x6460
-rwxr-xr-xtaler-android-build/x8662
19 files changed, 463 insertions, 27 deletions
diff --git a/common.gypi b/common.gypi
index 54a8d930c4..c8e897c432 100644
--- a/common.gypi
+++ b/common.gypi
@@ -130,8 +130,8 @@
'ldflags': [ '-Wl,-bbigtoc' ],
}],
['OS == "android"', {
- 'cflags': [ '-fPIE' ],
- 'ldflags': [ '-fPIE', '-pie' ]
+ 'cflags': [ '-fPIC' ],
+ 'ldflags': [ '-fPIC' ]
}],
],
'msvs_settings': {
@@ -190,8 +190,8 @@
],
},],
['OS == "android"', {
- 'cflags': [ '-fPIE' ],
- 'ldflags': [ '-fPIE', '-pie' ]
+ 'cflags': [ '-fPIC' ],
+ 'ldflags': [ '-fPIC' ]
}],
],
'msvs_settings': {
diff --git a/configure.py b/configure.py
index 48624aba92..0795e17d5f 100755
--- a/configure.py
+++ b/configure.py
@@ -1117,14 +1117,18 @@ def configure_node(o):
o['variables']['node_shared'] = b(options.shared)
node_module_version = getmoduleversion.get_version()
- if sys.platform == 'darwin':
- shlib_suffix = '%s.dylib'
- elif sys.platform.startswith('aix'):
- shlib_suffix = '%s.a'
+ if options.dest_os == 'android':
+ shlib_suffix = "so"
else:
shlib_suffix = 'so.%s'
+ if sys.platform == 'darwin':
+ shlib_suffix = '%s.dylib'
+ elif sys.platform.startswith('aix'):
+ shlib_suffix = '%s.a'
+ else:
+ shlib_suffix = 'so.%s'
+ shlib_suffix %= node_module_version
- shlib_suffix %= node_module_version
o['variables']['node_module_version'] = int(node_module_version)
o['variables']['shlib_suffix'] = shlib_suffix
@@ -1760,6 +1764,8 @@ gyp_args += args
if warn.warned and not options.verbose:
warn('warnings were emitted in the configure phase')
+print("gyp args", gyp_args)
+
print_verbose("running: \n " + " ".join(['python', 'tools/gyp_node.py'] + gyp_args))
run_gyp(gyp_args)
info('configure completed successfully')
diff --git a/deps/cares/config/android/ares_config.h b/deps/cares/config/android/ares_config.h
index 1a5265a509..2d469d5ca7 100644
--- a/deps/cares/config/android/ares_config.h
+++ b/deps/cares/config/android/ares_config.h
@@ -128,7 +128,7 @@
#define HAVE_GETNAMEINFO 1
/* Define to 1 if you have the getservbyport_r function. */
-#define HAVE_GETSERVBYPORT_R 1
+#undef HAVE_GETSERVBYPORT_R
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
diff --git a/deps/openssl/openssl-cl_no_asm.gypi b/deps/openssl/openssl-cl_no_asm.gypi
index bb9e55de91..5152774241 100644
--- a/deps/openssl/openssl-cl_no_asm.gypi
+++ b/deps/openssl/openssl-cl_no_asm.gypi
@@ -14,6 +14,8 @@
'includes': ['config/archs/linux64-s390x/no-asm/openssl-cl.gypi'],
}, 'target_arch=="arm" and OS=="linux"', {
'includes': ['config/archs/linux-armv4/no-asm/openssl-cl.gypi'],
+ }, 'target_arch=="arm" and OS=="android"', {
+ 'includes': ['config/archs/linux-armv4/no-asm/openssl-cl.gypi'],
}, 'target_arch=="arm64" and OS=="linux"', {
'includes': ['config/archs/linux-aarch64/no-asm/openssl-cl.gypi'],
}, 'target_arch=="arm64" and OS=="win"', {
diff --git a/deps/openssl/openssl_no_asm.gypi b/deps/openssl/openssl_no_asm.gypi
index 8eb61d9703..bf7d48749a 100644
--- a/deps/openssl/openssl_no_asm.gypi
+++ b/deps/openssl/openssl_no_asm.gypi
@@ -15,6 +15,8 @@
'includes': ['config/archs/linux64-s390x/no-asm/openssl.gypi'],
}, 'target_arch=="arm" and OS=="linux"', {
'includes': ['config/archs/linux-armv4/no-asm/openssl.gypi'],
+ }, 'target_arch=="arm" and OS=="android"', {
+ 'includes': ['config/archs/linux-armv4/no-asm/openssl.gypi'],
}, 'target_arch=="arm64" and OS=="linux"', {
'includes': ['config/archs/linux-aarch64/no-asm/openssl.gypi'],
}, 'target_arch=="ia32" and OS=="freebsd"', {
diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c
index 0f7c4c5d3a..728443d57a 100644
--- a/deps/uvwasi/src/uvwasi.c
+++ b/deps/uvwasi/src/uvwasi.c
@@ -1187,12 +1187,7 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
dir->nentries = UVWASI__READDIR_NUM_ENTRIES;
uv_fs_req_cleanup(&req);
-#ifndef _WIN32
- /* TODO(cjihrig): Need a Windows equivalent of this logic. */
- /* Seek to the proper location in the directory. */
- if (cookie != UVWASI_DIRCOOKIE_START)
- seekdir(dir->dir, cookie);
-#endif
+ /* seekdir does not exist on android */
/* Read the directory entries into the provided buffer. */
err = UVWASI_ESUCCESS;
@@ -1209,16 +1204,9 @@ uvwasi_errno_t uvwasi_fd_readdir(uvwasi_t* uvwasi,
consistently across platforms. In other words, d_next should always
be 8 bytes, d_ino should always be 8 bytes, d_namlen should always be
4 bytes, and d_type should always be 1 byte. */
-#ifndef _WIN32
- tell = telldir(dir->dir);
- if (tell < 0) {
- err = uvwasi__translate_uv_error(uv_translate_sys_error(errno));
- uv_fs_req_cleanup(&req);
- goto exit;
- }
-#else
+
+ /* seekdir does not exist on android */
tell = 0; /* TODO(cjihrig): Need to support Windows. */
-#endif /* _WIN32 */
name_len = strlen(dirents[i].name);
dirent.d_next = (uvwasi_dircookie_t) tell;
diff --git a/deps/v8/DEPS b/deps/v8/DEPS
index 0faa57e5b0..83752a4acc 100644
--- a/deps/v8/DEPS
+++ b/deps/v8/DEPS
@@ -168,7 +168,6 @@ deps = {
},
'v8/third_party/catapult': {
'url': Var('chromium_url') + '/catapult.git' + '@' + 'b9fad2fbcc499b984d88f4c4aec26d162297efae',
- 'condition': 'checkout_android',
},
'v8/third_party/colorama/src': {
'url': Var('chromium_url') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8',
diff --git a/deps/v8/tools/node/fetch_deps.py b/deps/v8/tools/node/fetch_deps.py
index ee5b629e2b..00eb4fc92d 100755
--- a/deps/v8/tools/node/fetch_deps.py
+++ b/deps/v8/tools/node/fetch_deps.py
@@ -35,7 +35,6 @@ GCLIENT_SOLUTION = [
"v8/test/test262/harness" : None,
"v8/third_party/android_ndk" : None,
"v8/third_party/android_sdk" : None,
- "v8/third_party/catapult" : None,
"v8/third_party/colorama/src" : None,
"v8/third_party/fuchsia-sdk" : None,
"v8/third_party/instrumented_libraries" : None,
diff --git a/lib/akono.js b/lib/akono.js
new file mode 100644
index 0000000000..4c2e2a2e0c
--- /dev/null
+++ b/lib/akono.js
@@ -0,0 +1,69 @@
+// Copyright (C) 2019 Taler Systems SA
+//
+// This file is part of GNU Taler.
+//
+// GNU Taler is free software: you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option)
+// any later version.
+//
+// GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+// more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with GNU. If not, see <https://www.gnu.org/licenses/>.
+
+
+'use strict';
+
+const akono = internalBinding("akono");
+
+const mod = require('module');
+mod._saved_findPath = mod._findPath;
+mod._akonoMods = {};
+mod._findPath = (request, paths, isMain) => {
+ const res = mod._saved_findPath(request, paths, isMain);
+ if (res !== false) return res;
+ const loadResult = akono.getModuleCode(request);
+ if (!loadResult) return false;
+ const p = `/vmod/${request}`;
+ mod._akonoMods[p] = loadResult;
+ return p;
+};
+
+function stripBOM(content) {
+ if (content.charCodeAt(0) === 0xFEFF) {
+ content = content.slice(1);
+ }
+ return content;
+}
+
+mod._saved_js_extension = mod._extensions[".js"];
+mod._extensions[".js"] = (module, filename) => {
+ if (mod._akonoMods.hasOwnProperty(filename)) {
+ const akmod = mod._akonoMods[filename];
+ const content = akmod;
+ module._compile(stripBOM(content), filename);
+ return;
+ }
+ return mod._saved_js_extension(module, filename);
+};
+
+mod._saved_json_extension = mod._extensions[".json"];
+mod._extensions[".json"] = (module, filename) => {
+ if (mod._akonoMods.hasOwnProperty(filename)) {
+ const akmod = mod._akonoMods[filename];
+ const content = akmod;
+ try {
+ module.exports = JSON.parse(stripBOM(content));
+ return;
+ } catch (err) {
+ err.message = filename + ': ' + err.message;
+ throw err;
+ }
+ }
+ return mod._saved_json_extension(module, filename);
+};
+
diff --git a/node.gyp b/node.gyp
index 7b971b5739..4b5b72a7b6 100644
--- a/node.gyp
+++ b/node.gyp
@@ -30,6 +30,7 @@
'lib/internal/bootstrap/pre_execution.js',
'lib/internal/per_context/primordials.js',
'lib/internal/per_context/domexception.js',
+ 'lib/akono.js',
'lib/async_hooks.js',
'lib/assert.js',
'lib/buffer.js',
@@ -497,6 +498,7 @@
'include_dirs': [
'src',
+ 'deps/v8/include',
'<(SHARED_INTERMEDIATE_DIR)' # for node_natives.h
],
'dependencies': [
diff --git a/node.gypi b/node.gypi
index 6954352b5e..dd4d701e91 100644
--- a/node.gypi
+++ b/node.gypi
@@ -68,6 +68,51 @@
[ 'node_enable_d8=="true"', {
'dependencies': [ 'tools/v8_gypfiles/d8.gyp:d8' ],
}],
+ [ 'node_use_bundled_v8=="false" and target_arch=="arm" and OS=="android"', {
+ 'libraries': [
+ '<!(pwd)/deps/v8/out.gn/android-arm/libv8_libbase.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm/libv8_libplatform.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm/libv8.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm/libicui18n.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm/libicuuc.cr.so',
+ ]
+ }],
+ [ 'node_use_bundled_v8=="false" and target_arch=="arm64" and OS=="android"', {
+ 'libraries': [
+ '<!(pwd)/deps/v8/out.gn/android-arm64/libv8_libbase.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm64/libv8_libplatform.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm64/libv8.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm64/libicui18n.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-arm64/libicuuc.cr.so',
+ ]
+ }],
+ [ 'node_use_bundled_v8=="false" and target_arch=="x86" and OS=="android"', {
+ 'libraries': [
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8_libbase.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8_libplatform.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libicui18n.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libicuuc.cr.so',
+ ]
+ }],
+ [ 'node_use_bundled_v8=="false" and target_arch=="ia32" and OS=="android"', {
+ 'libraries': [
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8_libbase.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8_libplatform.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libv8.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libicui18n.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x86/libicuuc.cr.so',
+ ]
+ }],
+ [ 'node_use_bundled_v8=="false" and target_arch=="x64" and OS=="android"', {
+ 'libraries': [
+ '<!(pwd)/deps/v8/out.gn/android-x64/libv8_libbase.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x64/libv8_libplatform.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x64/libv8.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x64/libicui18n.cr.so',
+ '<!(pwd)/deps/v8/out.gn/android-x64/libicuuc.cr.so',
+ ]
+ }],
[ 'node_use_bundled_v8=="true"', {
'dependencies': [
'tools/v8_gypfiles/v8.gyp:v8_maybe_snapshot',
diff --git a/taler-android-build/.gitignore b/taler-android-build/.gitignore
new file mode 100644
index 0000000000..724bbe1c11
--- /dev/null
+++ b/taler-android-build/.gitignore
@@ -0,0 +1 @@
+compiled/
diff --git a/taler-android-build/README b/taler-android-build/README
new file mode 100644
index 0000000000..fdac6b7d39
--- /dev/null
+++ b/taler-android-build/README
@@ -0,0 +1 @@
+names are based on the v8 CPU names
diff --git a/taler-android-build/arm b/taler-android-build/arm
new file mode 100755
index 0000000000..69c130054a
--- /dev/null
+++ b/taler-android-build/arm
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir
+
+NDK=$1
+
+API_LEVEL=21
+BUILD_HOST_TAG='linux-x86_64'
+TOOLCHAIN_DIR=$NDK/toolchains/llvm/prebuilt/$BUILD_HOST_TAG/
+
+if [[ ! -d "$NDK" ]]; then
+ echo "Android NDK directory '$NDK' invalid"
+ exit 1
+fi
+
+if [[ ! -d "$TOOLCHAIN_DIR" ]]; then
+ echo "Toolchain directory '$TOOLCHAIN_DIR' invalid"
+ exit 1
+fi
+
+##########
+# Build V8
+##########
+
+./build-android-v8 "$NDK" arm
+
+cd $scriptdir/..
+x=$scriptdir/compiled/armeabi-v7a/
+mkdir -p $x
+cp deps/v8/out.gn/android-arm/*.so $x/
+
+
+############
+# Build Node
+############
+
+cd $scriptdir
+
+export DEST_CPU_ARCH=arm
+
+# The naming of these isn't very consistent, as some tools start with arm,
+# others with arm7a.
+export AR=$TOOLCHAIN_DIR/bin/arm-linux-androideabi-ar
+export LD=$TOOLCHAIN_DIR/bin/arm-linux-androideabi-ld
+export RANLIB=$TOOLCHAIN_DIR/bin/arm-linux-androideabi-ranlib
+export STRIP=$TOOLCHAIN_DIR/bin/arm-linux-androideabi-strip
+
+export LINK=$TOOLCHAIN_DIR/bin/armv7a-linux-androideabi$API_LEVEL-clang++
+export CC=$TOOLCHAIN_DIR/bin/armv7a-linux-androideabi$API_LEVEL-clang
+export CXX=$TOOLCHAIN_DIR/bin/armv7a-linux-androideabi$API_LEVEL-clang++
+
+export CXXFLAGS='-D_LIBCPP_HAS_NO_OFF_T_FUNCTIONS'
+
+./build-android-node "$1" arm
+
+cd $scriptdir/..
+x=$scriptdir/compiled/armeabi-v7a/
+mkdir -p $x
+cp out/Release/lib/libnode.so $x/
diff --git a/taler-android-build/arm64 b/taler-android-build/arm64
new file mode 100755
index 0000000000..31bf46c13a
--- /dev/null
+++ b/taler-android-build/arm64
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir
+
+NDK=$1
+
+API_LEVEL=21
+BUILD_HOST_TAG='linux-x86_64'
+TOOLCHAIN_DIR=$NDK/toolchains/llvm/prebuilt/$BUILD_HOST_TAG/
+
+if [[ ! -d "$NDK" ]]; then
+ echo "Android NDK directory '$NDK' invalid"
+ exit 1
+fi
+
+if [[ ! -d "$TOOLCHAIN_DIR" ]]; then
+ echo "Toolchain directory '$TOOLCHAIN_DIR' invalid"
+ exit 1
+fi
+
+##########
+# Build V8
+##########
+
+./build-android-v8 "$1" arm64
+
+cd $scriptdir/..
+x=$scriptdir/compiled/arm64-v8a/
+mkdir -p $x
+cp deps/v8/out.gn/android-arm64/*.so $x/
+
+
+
+############
+# Build Node
+############
+
+# The naming of these isn't very consistent, as some tools start with arm,
+# others with arm7a.
+export AR=$TOOLCHAIN_DIR/bin/aarch64-linux-android-ar
+export LD=$TOOLCHAIN_DIR/bin/aarch64-linux-android-ld
+export RANLIB=$TOOLCHAIN_DIR/bin/aarch64-linux-android-ranlib
+export STRIP=$TOOLCHAIN_DIR/bin/aarch64-linux-android-strip
+
+export CC=$TOOLCHAIN_DIR/bin/aarch64-linux-android$API_LEVEL-clang
+export CXX=$TOOLCHAIN_DIR/bin/aarch64-linux-android$API_LEVEL-clang++
+export LINK=$TOOLCHAIN_DIR/bin/aarch64-linux-android$API_LEVEL-clang++
+
+export DEST_CPU_ARCH=arm64
+
+cd $scriptdir
+
+./build-android-node "$1" arm64
+
+cd $scriptdir/..
+x=$scriptdir/compiled/arm64-v8a/
+mkdir -p $x
+cp out/Release/lib/libnode.so $x/
diff --git a/taler-android-build/build-android-node b/taler-android-build/build-android-node
new file mode 100755
index 0000000000..c9e5a41da5
--- /dev/null
+++ b/taler-android-build/build-android-node
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+# This script assumes that all the right environment variables
+# (CC, LD, STRIP, ...) areset.
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir/..
+
+export GYP_DEFINES="OS=android clang=1"
+
+function myconf() {
+ ./configure \
+ --ninja \
+ --cross-compiling \
+ --dest-cpu=$DEST_CPU_ARCH \
+ --dest-os=android \
+ --without-intl \
+ --openssl-no-asm \
+ --without-bundled-v8 \
+ --shared
+}
+
+myconf && make
diff --git a/taler-android-build/build-android-v8 b/taler-android-build/build-android-v8
new file mode 100755
index 0000000000..70057b9c5e
--- /dev/null
+++ b/taler-android-build/build-android-v8
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir/..
+
+NDK=$1
+DEST_CPU_ARCH=$2
+
+if [[ ! -d "$NDK" ]]; then
+ echo "Android NDK directory '$NDK' invalid"
+ exit 1
+fi
+
+ln -fs $NDK ./deps/v8/third_party/android_ndk
+
+# We do not export anything about the tool chain, as v8
+# will pick their own toolchain for android from the ndk
+
+cd ./deps/v8
+
+python3 ./tools/node/fetch_deps.py $PWD
+
+gn_args=$(cat <<EOF
+is_official_build = true
+is_debug = false
+v8_enable_backtrace = false
+v8_enable_slow_dchecks = true
+v8_optimized_debug = false
+v8_target_cpu = "$DEST_CPU_ARCH"
+target_os="android"
+target_cpu="$DEST_CPU_ARCH"
+is_component_build=true
+v8_android_log_stdout=true
+v8_use_external_startup_data=false
+v8_enable_debugging_features=false
+v8_enable_embedded_builtins=true
+is_clang=true
+use_custom_libcxx=false
+EOF
+)
+
+echo gn_args $gn_args
+
+echo "executing gn gen"
+
+./buildtools/linux64/gn gen out.gn/android-$DEST_CPU_ARCH "--args=$gn_args"
+
+echo "executing ninja"
+
+./_depot_tools/ninja -C out.gn/android-$DEST_CPU_ARCH v8 d8
diff --git a/taler-android-build/x64 b/taler-android-build/x64
new file mode 100755
index 0000000000..22002bdd3e
--- /dev/null
+++ b/taler-android-build/x64
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir
+
+NDK=$1
+
+API_LEVEL=21
+BUILD_HOST_TAG='linux-x86_64'
+TOOLCHAIN_DIR=$NDK/toolchains/llvm/prebuilt/$BUILD_HOST_TAG/
+
+if [[ ! -d "$NDK" ]]; then
+ echo "Android NDK directory '$NDK' invalid"
+ exit 1
+fi
+
+if [[ ! -d "$TOOLCHAIN_DIR" ]]; then
+ echo "Toolchain directory '$TOOLCHAIN_DIR' invalid"
+ exit 1
+fi
+
+##########
+# Build V8
+##########
+
+./build-android-v8 "$NDK" x64
+
+cd $scriptdir/..
+x=$scriptdir/compiled/x86_64/
+mkdir -p $x
+cp deps/v8/out.gn/android-x64/*.so $x/
+
+
+############
+# Build Node
+############
+
+cd $scriptdir
+
+export DEST_CPU_ARCH=x64
+
+# The naming of these isn't very consistent, as some tools start with arm,
+# others with arm7a.
+export AR=$TOOLCHAIN_DIR/bin/x86_64-linux-android-ar
+export LD=$TOOLCHAIN_DIR/bin/x86_64-linux-android-ld
+export RANLIB=$TOOLCHAIN_DIR/bin/x86_64-linux-android-ranlib
+export STRIP=$TOOLCHAIN_DIR/bin/x86_64-linux-android-strip
+
+export LINK=$TOOLCHAIN_DIR/bin/x86_64-linux-android$API_LEVEL-clang++
+export CC=$TOOLCHAIN_DIR/bin/x86_64-linux-android$API_LEVEL-clang
+export CXX=$TOOLCHAIN_DIR/bin/x86_64-linux-android$API_LEVEL-clang++
+
+./build-android-node "$1" x64
+
+cd $scriptdir/..
+x=$scriptdir/compiled/x86_64/
+mkdir -p $x
+cp out/Release/lib/libnode.so $x/
diff --git a/taler-android-build/x86 b/taler-android-build/x86
new file mode 100755
index 0000000000..f1a5d582d6
--- /dev/null
+++ b/taler-android-build/x86
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail
+
+scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd $scriptdir
+
+NDK=$1
+
+API_LEVEL=21
+BUILD_HOST_TAG='linux-x86_64'
+TOOLCHAIN_DIR=$NDK/toolchains/llvm/prebuilt/$BUILD_HOST_TAG/
+
+if [[ ! -d "$NDK" ]]; then
+ echo "Android NDK directory '$NDK' invalid"
+ exit 1
+fi
+
+if [[ ! -d "$TOOLCHAIN_DIR" ]]; then
+ echo "Toolchain directory '$TOOLCHAIN_DIR' invalid"
+ exit 1
+fi
+
+##########
+# Build V8
+##########
+
+./build-android-v8 "$NDK" x86
+
+cd $scriptdir/..
+x=$scriptdir/compiled/x86/
+mkdir -p $x
+cp deps/v8/out.gn/android-x86/*.so $x/
+
+
+############
+# Build Node
+############
+
+cd $scriptdir
+
+export DEST_CPU_ARCH=x86
+
+# The naming of these isn't very consistent, as some tools start with arm,
+# others with arm7a.
+export AR=$TOOLCHAIN_DIR/bin/i686-linux-android-ar
+export LD=$TOOLCHAIN_DIR/bin/i686-linux-android-ld
+export RANLIB=$TOOLCHAIN_DIR/bin/i686-linux-android-ranlib
+export STRIP=$TOOLCHAIN_DIR/bin/i686-linux-android-strip
+
+export LINK=$TOOLCHAIN_DIR/bin/i686-linux-android$API_LEVEL-clang++
+export CC=$TOOLCHAIN_DIR/bin/i686-linux-android$API_LEVEL-clang
+export CXX=$TOOLCHAIN_DIR/bin/i686-linux-android$API_LEVEL-clang++
+
+export CXXFLAGS='-D_LIBCPP_HAS_NO_OFF_T_FUNCTIONS'
+
+./build-android-node "$1" x86
+
+cd $scriptdir/..
+x=$scriptdir/compiled/x86/
+mkdir -p $x
+cp out/Release/lib/libnode.so $x/