staltz / sodium-native-nodejs-mobile

Low level bindings for libsodium

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

sodium.node is wrong architecture for Android

RangerMauve opened this issue · comments

I installed sodium-native-nodejs-mobile and got it to compile into the APK by cleaning out the libsodium folder.

However, when I try to require sodium-native-nodejs-mobile inside the nodejs-mobile project, I get the following stack trace:

10-13 16:03:38.486  9366  9453 E nodejs  : /data/data/com.teliosmobile/files/nodejs-project/node_modules/bindings/bindings.js:91
10-13 16:03:38.486  9366  9453 E nodejs  :         throw e
10-13 16:03:38.486  9366  9453 E nodejs  :         ^
10-13 16:03:38.486  9366  9453 E nodejs  : 
10-13 16:03:38.486  9366  9453 E nodejs  : Error: dlopen failed: "/data/data/com.teliosmobile/files/nodejs-project/node_modules/sodium-native-nodejs-mobile/build/Release/sodium.node" is for EM_X86_64 (62) instead of EM_AARCH64 (183)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Object.Module._extensions..node (internal/modules/cjs/loader.js:1065:18)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Module.load (internal/modules/cjs/loader.js:879:32)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Function.Module._load (internal/modules/cjs/loader.js:724:14)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Module.require (internal/modules/cjs/loader.js:903:19)
10-13 16:03:38.486  9366  9453 E nodejs  :     at require (internal/modules/cjs/helpers.js:74:18)
10-13 16:03:38.486  9366  9453 E nodejs  :     at bindings (/data/data/com.teliosmobile/files/nodejs-project/node_modules/bindings/bindings.js:84:48)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Object.<anonymous> (/data/data/com.teliosmobile/files/nodejs-project/node_modules/sodium-native-nodejs-mobile/index.js:1:33)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Module._compile (internal/modules/cjs/loader.js:1015:30)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)
10-13 16:03:38.486  9366  9453 E nodejs  :     at Module.load (internal/modules/cjs/loader.js:879:32)

As well, when I use objdump to inspect the sodium.node binary, I'm seeing the following:

objdump -f ./build/Release/sodium.node 

./build/Release/sodium.node:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000001040

This is telling me that it's not compiled for arm64, however I'm not seeing anything in the instructions or build scripts that would enable this functionality. 😅

I've tried stuff like specifying the architecture and platform for npm install, and that doesn't seem to help either. e.g. npm i --save sodium-native-nodejs-mobile --target_arch=arm64 --target_platform=android

I've also tried to rebuild with the target_arch argument, and the binary still seems to be x86-64. node-gyp clean configure rebuild --verbose --target_arch=arm64

What's strangeis that using target_arch=ia32 seems to compile the binary as expected.

node-gyp clean configure rebuild --verbose --target_arch=ia32

...

objdump -f ./build/Release/sodium.node 

./build/Release/sodium.node:     file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00001050

Any pointers would be very much appreciated!

I think this is supposed to be solved by nodejs-mobile recompiling stuff with .gyp in it at runtime. Not seeing that though.

Hey @RangerMauve

It sounds like you're using conventional npm install and node-gyp to compile, and that's likely to be incorrect. nodejs-mobile has its own fork of node-gyp called nodejs-mobile-gyp and it runs as part of the Android compilation of the APK. Have you seen https://github.com/nodejs-mobile/nodejs-mobile-react-native#native-modules ?

Interesting. It seems like that Android compilation isn't invoking the code that does the nodejs-mobile-gyp code. :/ Have you seen this before?

Do I need to be running something other than react-native run-android to make it work? 😅

Thank you for the pointer @staltz! That helped me narrow down where to look. After I read the how the gradle script does native compilation I came up with the following:

Deleting the build folder inside sodium-native-nodejs-mobile then running NODEJS_MOBILE_BUILD_NATIVE_MODULES=1 react-native run-android seems to have forced recompliation and I'm now getting the following error which seems unrelated to this specific Github issue. 😅

Metro has encountered an error: SHA-1 for file /home/mauve/.nvm/versions/node/v15.2.1/lib/node_modules/react-native/node_modules/metro-runtime/src/polyfills/require.js (/home/mauve/.nvm/versions/node/v15.2.1/lib/node_modules/react-native/node_modules/metro-runtime/src/polyfills/require.js) is not computed.
         Potential causes:
           1) You have symlinks in your project - watchman does not follow symlinks.
           2) Check `blockList` in your metro.config.js and make sure it isn't excluding the file path.: /home/mauve/.nvm/versions/node/v15.2.1/lib/node_modules/react-native/node_modules/metro/src/node-haste/DependencyGraph.js (245:13)

�[0m �[90m 243 |�[39m�[0m
�[0m �[90m 244 |�[39m     �[36mif�[39m (�[33m!�[39msha1) {�[0m
�[0m�[31m�[1m>�[22m�[39m�[90m 245 |�[39m       �[36mthrow�[39m �[36mnew�[39m �[33mReferenceError�[39m(�[32m`SHA-1 for file ${filename} (${resolvedPath}) is not computed.�[39m�[0m
�[0m �[90m     |�[39m             �[31m�[1m^�[22m�[39m�[0m
�[0m �[90m 246 |�[39m �[32m         Potential causes:�[39m�[0m
�[0m �[90m 247 |�[39m �[32m           1) You have symlinks in your project - watchman does not follow symlinks.�[39m�[0m
�[0m �[90m 248 |�[39m �[32m           2) Check \`blockList\` in your metro.config.js and make sure it isn't excluding the file path.`�[39m)�[33m;�[39m�[0m

Great to hear that you figured it out! It may seem like I have all the answers but in reality I wouldn't have known that you have to delete that folder. So many things can go wrong, it seems.

About this new error, I think you have to tell metro (react-native's browserify) to ignore the JS files that are in the nodejs-project. Check Manyverse's metro config file in the project root for an example.

I've actually added the blocklist according to the nodejs-mobile docs (with updated to account for the change from blacklist to blocklist)

/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true
      }
    })
  },
  resolver: {
    blockList: [
      /\/nodejs-assets\/.*/,
      /\/android\/.*/,
      /\/ios\/.*/
    ]
  }
}

I'll try the manyverse one to see if it helps. Thanks for the tip!

Clearning the NPM cache and adding resetCache: true to my metro.config seems to have helped. Running into other issues now.

Mobile apps are hell. :P

Err, looks like it was a false alarm. Still doesn't seem to be building. 😅

It seems that my project properties didn't contain a reactNativeDebugArchitectures property, and this the abiFilters for the NDKI were null.

To fix it I added the ndk.abiFilters property to the defaultConfig in my android/app/build.gradle. (this was originally generated by react-native. You can see an example of this in manyverse' build here: https://gitlab.com/staltz/manyverse/-/blob/master/android/app/build.gradle#L159