Skip to content

Commit 17a21ac

Browse files
build: commit some android build and test fixtures
This commit contains some test fixes as well as build fixes for Android which I have been maintaining for Termux since a few years now. The full list of patches can be found at https://github.com/termux/termux-packages/tree/master/packages/nodejs and https://github.com/termux/termux-packages/tree/master/packages/nodejs-lts Not all the patches from the above sources are being committed over here as a some off them are specific to Termux. This does not fix the builds for Android completely, I was not able to successfully build Node locally according to the build instructions for Android, but I was able to build with the patches as in the above two URLs, in a separate environment. The build scripts used to build Node can be found in build.sh in the above directories linked. Here's a summary of what's changed: - Older Android versions doesn't have /dev/stdin, /dev/stdout, or /dev/stderr. Although this seems to have changed now, I can see that they exist on my new phone. Anyways these are specifically listed as not being the part of the POSIX standard. https://pubs.opengroup.org/onlinepubs/9799919799/ (See 2.1.1 Requirements, the last bullet point of 4th point specifically states that these three character special files are non- standard extension). The tests making use of /dev/stdin have been modified to use /proc/self/fd/0 which is guaranteed to exist on all POSIX platforms - Some other tests where Linux kernel behavior is different from other platforms (buffer size tests) have been patched to treat Android as Linux since Android makes use of the Linux kernel under the hood. - tools/v8_gypfiles/toolchain.gypi adds -m32 to host build flags when compiling for 32 bit target architecture. But in common.gypi adding -m64 conflicts with it which may cause compilation errors. Having both -m32 and -m64 may raise errors that are hard to debug. This patch probably needs to be improved but works good enough for Android builds. This probably hasn't been noticed yet because cross-compilations aren't that common for other platforms, Android has no other option but to cross compile. android-patches/common.gypi.patch does fix the builds for 32-bit architectures on 64-bit host, by not not adding -m64 to host build when cross compiling for 32-bit. - android-patches/v8.gyp.patch fixes assembly errors during cross compilation for 32-bit on 64-bit host. This patch is needed for the same reason as for the above patch - android-patches/trap-handler.h.patch has been updated so that it applies cleanly in the new source tree. - libuv does not implement uv_udp_set_source_membership for Android, OpenBSD and FreeBSD. So for these platforms it returns ENOSYS instead of EINVAL in tests. Tests have been patched to reflect this
1 parent b140283 commit 17a21ac

18 files changed

+110
-34
lines changed

android-patches/common.gypi.patch

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
diff --git a/common.gypi b/common.gypi
2+
index 5e39ad3f09..1e535f48a8 100644
3+
--- a/common.gypi
4+
+++ b/common.gypi
5+
@@ -520,11 +520,11 @@
6+
}],
7+
['_toolset=="host"', {
8+
'conditions': [
9+
- [ 'host_arch=="ia32"', {
10+
+ [ 'host_arch=="ia32" or (target_arch=="ia32" or target_arch=="arm")', {
11+
'cflags': [ '-m32' ],
12+
'ldflags': [ '-m32' ],
13+
}],
14+
- [ 'host_arch=="x64"', {
15+
+ [ 'host_arch=="x64" and (target_arch=="x64" or target_arch=="arm64")', {
16+
'cflags': [ '-m64' ],
17+
'ldflags': [ '-m64' ],
18+
}],

android-patches/trap-handler.h.patch

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,50 @@
1-
--- trap-handler.h 2022-08-11 09:01:23.384000000 +0800
2-
+++ fixed-trap-handler.h 2022-08-11 09:09:15.352000000 +0800
3-
@@ -17,23 +17,7 @@
1+
diff --git a/deps/v8/src/trap-handler/trap-handler.h b/deps/v8/src/trap-handler/trap-handler.h
2+
index 74967a00c1..d4f3b40269 100644
3+
--- a/deps/v8/src/trap-handler/trap-handler.h
4+
+++ b/deps/v8/src/trap-handler/trap-handler.h
5+
@@ -17,45 +17,7 @@ namespace v8 {
46
namespace internal {
57
namespace trap_handler {
6-
8+
79
-// X64 on Linux, Windows, MacOS, FreeBSD.
810
-#if V8_HOST_ARCH_X64 && V8_TARGET_ARCH_X64 && \
911
- ((V8_OS_LINUX && !V8_OS_ANDROID) || V8_OS_WIN || V8_OS_DARWIN || \
1012
- V8_OS_FREEBSD)
1113
-#define V8_TRAP_HANDLER_SUPPORTED true
12-
-// Arm64 (non-simulator) on Mac.
13-
-#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && V8_OS_DARWIN
14+
-// Arm64 (non-simulator) on Mac and Linux.
15+
-#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && \
16+
- (V8_OS_DARWIN || (V8_OS_LINUX && !V8_OS_ANDROID))
1417
-#define V8_TRAP_HANDLER_SUPPORTED true
1518
-// Arm64 simulator on x64 on Linux, Mac, or Windows.
19+
-//
20+
-// The simulator case uses some inline assembly code, which cannot be
21+
-// compiled with MSVC, so don't enable the trap handler in that case.
22+
-// (MSVC #defines _MSC_VER, but so does Clang when targeting Windows, hence
23+
-// the check for __clang__.)
1624
-#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_X64 && \
17-
- (V8_OS_LINUX || V8_OS_DARWIN)
25+
- (V8_OS_LINUX || V8_OS_DARWIN || V8_OS_WIN) && \
26+
- (!defined(_MSC_VER) || defined(__clang__))
27+
-#define V8_TRAP_HANDLER_VIA_SIMULATOR
28+
-#define V8_TRAP_HANDLER_SUPPORTED true
29+
-// Loong64 (non-simulator) on Linux.
30+
-#elif V8_TARGET_ARCH_LOONG64 && V8_HOST_ARCH_LOONG64 && V8_OS_LINUX
31+
-#define V8_TRAP_HANDLER_SUPPORTED true
32+
-// Loong64 simulator on x64 on Linux
33+
-#elif V8_TARGET_ARCH_LOONG64 && V8_HOST_ARCH_X64 && V8_OS_LINUX
34+
-#define V8_TRAP_HANDLER_VIA_SIMULATOR
35+
-#define V8_TRAP_HANDLER_SUPPORTED true
36+
-// RISCV64 (non-simulator) on Linux.
37+
-#elif V8_TARGET_ARCH_RISCV64 && V8_HOST_ARCH_RISCV64 && V8_OS_LINUX && \
38+
- !V8_OS_ANDROID
39+
-#define V8_TRAP_HANDLER_SUPPORTED true
40+
-// RISCV64 simulator on x64 on Linux
41+
-#elif V8_TARGET_ARCH_RISCV64 && V8_HOST_ARCH_X64 && V8_OS_LINUX
1842
-#define V8_TRAP_HANDLER_VIA_SIMULATOR
1943
-#define V8_TRAP_HANDLER_SUPPORTED true
2044
-// Everything else is unsupported.
2145
-#else
2246
#define V8_TRAP_HANDLER_SUPPORTED false
2347
-#endif
24-
25-
// Setup for shared library export.
26-
#if defined(BUILDING_V8_SHARED) && defined(V8_OS_WIN)
48+
49+
#if V8_OS_ANDROID && V8_TRAP_HANDLER_SUPPORTED
50+
// It would require some careful security review before the trap handler

android-patches/v8.gyp.patch

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp
2+
index 1dd0b971d4..36b7c704dd 100644
3+
--- a/tools/v8_gypfiles/v8.gyp
4+
+++ b/tools/v8_gypfiles/v8.gyp
5+
@@ -1989,12 +1989,12 @@
6+
],
7+
}, { # 'OS!="win"'
8+
'conditions': [
9+
- ['_toolset == "host" and host_arch == "x64" or _toolset == "target" and target_arch=="x64"', {
10+
+ ['_toolset == "host" and host_arch == "x64" and (target_arch == "x64" or target_arch == "arm64") or (_toolset == "target" and target_arch == "x64")', {
11+
'sources': [
12+
'<(V8_ROOT)/src/heap/base/asm/x64/push_registers_asm.cc',
13+
],
14+
}],
15+
- ['_toolset == "host" and host_arch == "ia32" or _toolset == "target" and target_arch=="ia32"', {
16+
+ ['_toolset == "host" and host_arch == "x64" and (target_arch == "arm" or target_arch == "ia32") or (_toolset == "target" and target_arch == "ia32")', {
17+
'sources': [
18+
'<(V8_ROOT)/src/heap/base/asm/ia32/push_registers_asm.cc',
19+
],

android_configure.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55
# TODO: In next version, it will be a JSON file listing all the patches, and then it will iterate through to apply them.
66
def patch_android():
77
print("- Patches List -")
8-
print("[1] [deps/v8/src/trap-handler/trap-handler.h] related to https://github.com/nodejs/node/issues/36287")
8+
print("[1] [common.gypi] related to cross-compiling for 32-bit architectures on 64-bit host")
9+
print("[2] [deps/v8/src/trap-handler/trap-handler.h] related to https://github.com/nodejs/node/issues/36287")
10+
print("[3] [tools/v8_gypfiles/v8.gyp] Pass -latomic to clang when cross-compiling for Android")
911
if platform.system() == "Linux":
10-
os.system('patch -f ./deps/v8/src/trap-handler/trap-handler.h < ./android-patches/trap-handler.h.patch')
12+
patches = [
13+
'./android-patches/common.gypi.patch',
14+
'./android-patches/trap-handler.h.patch',
15+
'./android-patches/v8.gyp.patch',
16+
]
17+
for patch in patches:
18+
print(f"Applying patch: {patch}")
19+
os.system('patch -p1 < ' + patch)
1120
print("\033[92mInfo: \033[0m" + "Tried to patch.")
1221

1322
if platform.system() != "Linux" and platform.system() != "Darwin":

test/common/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const isFreeBSD = process.platform === 'freebsd';
121121
const isOpenBSD = process.platform === 'openbsd';
122122
const isLinux = process.platform === 'linux';
123123
const isMacOS = process.platform === 'darwin';
124+
const isAndroid = process.platform === 'android';
124125
const isASan = process.config.variables.asan === 1;
125126
const isRiscv64 = process.arch === 'riscv64';
126127
const isDebug = process.features.debug;
@@ -891,6 +892,7 @@ const common = {
891892
isLinux,
892893
isOpenBSD,
893894
isMacOS,
895+
isAndroid,
894896
isPi,
895897
isSunOS,
896898
isWindows,

test/parallel/test-cluster-bind-privileged-port.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const cluster = require('cluster');
2626
const net = require('net');
2727
const { readFileSync } = require('fs');
2828

29-
if (common.isLinux) {
29+
if (common.isLinux || common.isAndroid) {
3030
try {
3131
const unprivilegedPortStart = parseInt(readFileSync('/proc/sys/net/ipv4/ip_unprivileged_port_start'));
3232
if (unprivilegedPortStart <= 42) {

test/parallel/test-cluster-shared-handle-bind-privileged-port.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ if (process.getuid() === 0)
3737

3838
// Some systems won't have port 42 set as a privileged port, in that
3939
// case, skip the test.
40-
if (common.isLinux) {
40+
if (common.isLinux || common.isAndroid) {
4141
const { readFileSync } = require('fs');
4242

4343
try {

test/parallel/test-dgram-bind-fd.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const BUFFER_SIZE = 4096;
7777
const sendBufferSize = socket.getSendBufferSize();
7878

7979
// note: linux will double the buffer size
80-
const expectedBufferSize = common.isLinux ?
80+
const expectedBufferSize = (common.isLinux || common.isAndroid) ?
8181
BUFFER_SIZE * 2 : BUFFER_SIZE;
8282
assert.strictEqual(recvBufferSize, expectedBufferSize);
8383
assert.strictEqual(sendBufferSize, expectedBufferSize);

test/parallel/test-dgram-membership.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ const setup = dgram.createSocket.bind(dgram, { type: 'udp4', reuseAddr: true });
106106
// addSourceSpecificMembership with invalid groupAddress should throw
107107
{
108108
const socket = setup();
109+
const errCode = (common.isAndroid || common.isOpenBSD || common.isFreeBSD) ? 'ENOSYS' : 'EINVAL';
109110
assert.throws(() => {
110111
socket.addSourceSpecificMembership(multicastAddress, '0');
111112
}, {
112-
code: 'EINVAL',
113-
message: 'addSourceSpecificMembership EINVAL'
113+
code: errCode,
114+
message: `addSourceSpecificMembership ${errCode}`
114115
});
115116
socket.close();
116117
}
@@ -144,11 +145,12 @@ const setup = dgram.createSocket.bind(dgram, { type: 'udp4', reuseAddr: true });
144145
// dropSourceSpecificMembership with invalid UDP should throw
145146
{
146147
const socket = setup();
148+
const errCode = (common.isAndroid || common.isOpenBSD || common.isFreeBSD) ? 'ENOSYS' : 'EINVAL';
147149
assert.throws(() => {
148150
socket.dropSourceSpecificMembership(multicastAddress, '0');
149151
}, {
150-
code: 'EINVAL',
151-
message: 'dropSourceSpecificMembership EINVAL'
152+
code: errCode,
153+
message: `dropSourceSpecificMembership ${errCode}`
152154
});
153155
socket.close();
154156
}

test/parallel/test-dgram-socket-buffer-size.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ function getExpectedError(type) {
114114
socket.setSendBufferSize(10000);
115115

116116
// note: linux will double the buffer size
117-
const expectedBufferSize = common.isLinux ? 20000 : 10000;
117+
const expectedBufferSize = (common.isLinux || common.isAndroid) ? 20000 : 10000;
118118
assert.strictEqual(socket.getRecvBufferSize(), expectedBufferSize);
119119
assert.strictEqual(socket.getSendBufferSize(), expectedBufferSize);
120120
socket.close();

test/parallel/test-fs-readfile-eof.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
const common = require('../common');
33

44
if (common.isWindows || common.isAIX || common.isIBMi)
5-
common.skip(`No /dev/stdin on ${process.platform}.`);
5+
common.skip(`No /proc/self/fd/0 on ${process.platform}.`);
66

77
const assert = require('assert');
88
const fs = require('fs/promises');
99
const childType = ['child-encoding', 'child-non-encoding'];
1010

1111
if (process.argv[2] === childType[0]) {
12-
fs.readFile('/dev/stdin', 'utf8').then((data) => {
12+
fs.readFile('/proc/self/fd/0', 'utf8').then((data) => {
1313
process.stdout.write(data);
1414
});
1515
return;
1616
} else if (process.argv[2] === childType[1]) {
17-
fs.readFile('/dev/stdin').then((data) => {
17+
fs.readFile('/proc/self/fd/0').then((data) => {
1818
process.stdout.write(data);
1919
});
2020
return;

test/parallel/test-fs-readfile-pipe-large.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ const common = require('../common');
44
// Simulate `cat readfile.js | node readfile.js`
55

66
if (common.isWindows || common.isAIX || common.isIBMi)
7-
common.skip(`No /dev/stdin on ${process.platform}.`);
7+
common.skip(`No /proc/self/fd/0 on ${process.platform}.`);
88

99
const assert = require('assert');
1010
const fs = require('fs');
1111

1212
if (process.argv[2] === 'child') {
13-
fs.readFile('/dev/stdin', function(er, data) {
13+
fs.readFile('/proc/self/fd/0', function(er, data) {
1414
assert.ifError(er);
1515
process.stdout.write(data);
1616
});

test/parallel/test-fs-readfile-pipe.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ const common = require('../common');
2525
// Simulate `cat readfile.js | node readfile.js`
2626

2727
if (common.isWindows || common.isAIX || common.isIBMi)
28-
common.skip(`No /dev/stdin on ${process.platform}.`);
28+
common.skip(`No /proc/self/fd/0 on ${process.platform}.`);
2929

3030
const assert = require('assert');
3131
const fs = require('fs');
3232

3333
if (process.argv[2] === 'child') {
34-
fs.readFile('/dev/stdin', common.mustSucceed((data) => {
34+
fs.readFile('/proc/self/fd/0', common.mustSucceed((data) => {
3535
process.stdout.write(data);
3636
}));
3737
return;

test/parallel/test-fs-readfilesync-pipe-large.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ const common = require('../common');
44
// Simulate `cat readfile.js | node readfile.js`
55

66
if (common.isWindows || common.isAIX || common.isIBMi)
7-
common.skip(`No /dev/stdin on ${process.platform}.`);
7+
common.skip(`No /proc/self/fd/0 on ${process.platform}.`);
88

99
const assert = require('assert');
1010
const fs = require('fs');
1111

1212
if (process.argv[2] === 'child') {
13-
process.stdout.write(fs.readFileSync('/dev/stdin', 'utf8'));
13+
process.stdout.write(fs.readFileSync('/proc/self/fd/0', 'utf8'));
1414
return;
1515
}
1616

test/parallel/test-fs-realpath-pipe.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
const common = require('../common');
44

55
if (common.isWindows || common.isAIX || common.isIBMi)
6-
common.skip(`No /dev/stdin on ${process.platform}.`);
6+
common.skip(`No /proc/self/fd/0 on ${process.platform}.`);
77

88
const assert = require('assert');
99

1010
const { spawnSync } = require('child_process');
1111

1212
for (const code of [
13-
`require('fs').realpath('/dev/stdin', (err, resolvedPath) => {
13+
`require('fs').realpath('/proc/self/fd/0', (err, resolvedPath) => {
1414
if (err) {
1515
console.error(err);
1616
process.exit(1);
@@ -20,7 +20,7 @@ for (const code of [
2020
}
2121
});`,
2222
`try {
23-
if (require('fs').realpathSync('/dev/stdin')) {
23+
if (require('fs').realpathSync('/proc/self/fd/0')) {
2424
process.exit(2);
2525
}
2626
} catch (e) {

test/parallel/test-process-constants-noatime.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const common = require('../common');
44
const assert = require('assert');
55
const constants = require('fs').constants;
66

7-
if (common.isLinux) {
7+
if (common.isLinux || common.isAndroid) {
88
assert('O_NOATIME' in constants);
99
assert.strictEqual(constants.O_NOATIME, 0x40000);
1010
} else {

test/sequential/test-fs-watch.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ if (!isMainThread) {
3737

3838
const expectFilePath = common.isWindows ||
3939
common.isLinux ||
40+
common.isAndroid ||
4041
common.isMacOS ||
4142
common.isAIX;
4243

tools/v8_gypfiles/v8.gyp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@
13221322
# Platforms that don't have Compare-And-Swap (CAS) support need to link atomic library
13231323
# to implement atomic memory access.
13241324
# Clang needs it for some atomic operations (https://clang.llvm.org/docs/Toolchain.html#atomics-library).
1325-
['(OS=="linux" and clang==1) or (v8_current_cpu in ["mips64", "mips64el", "arm", "riscv64", "loong64"])', {
1325+
['((OS=="linux" or OS=="android") and clang==1) or (v8_current_cpu in ["mips64", "mips64el", "ppc", "arm", "riscv64", "loong64"])', {
13261326
'link_settings': {
13271327
'libraries': ['-latomic', ],
13281328
},
@@ -1466,6 +1466,7 @@
14661466
'<(V8_ROOT)/src/base/platform/platform-posix.h',
14671467
'<(V8_ROOT)/src/base/platform/platform-posix-time.cc',
14681468
'<(V8_ROOT)/src/base/platform/platform-posix-time.h',
1469+
'<(V8_ROOT)/src/base/platform/platform-linux.h',
14691470
],
14701471
'link_settings': {
14711472
'target_conditions': [

0 commit comments

Comments
 (0)