objectbox / objectbox-dart

Flutter database for super-fast Dart object persistence
https://docs.objectbox.io/getting-started
Apache License 2.0
927 stars 115 forks source link

Issue running on on NixOS #548

Open MrCyjaneK opened 10 months ago

MrCyjaneK commented 10 months ago

Basic info:

Steps to reproduce

  1. Build a project that uses objectbox_flutter_libs (or libobjectbox.so)
  2. Try to run it
  3. :(

Expected behavior

App would run

Code

N/A

Logs, stack traces

$ flutter run --device-id linux
{...}
flutter: Failed to load ObjectBox library. For Flutter apps, check if objectbox_flutter_libs is added to dependencies. For unit tests and Dart apps, check if the ObjectBox library was downloaded (https://docs.objectbox.io/getting-started).
flutter: Failed to load ObjectBox library. For Flutter apps, check if objectbox_flutter_libs is added to dependencies. For unit tests and Dart apps, check if the ObjectBox library was downloaded (https://docs.objectbox.io/getting-started).
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to load dynamic library 'libobjectbox.so': libobjectbox.so: cannot open shared object file: No such file or directory
#0      _open (dart:ffi-patch/ffi_dynamic_library_patch.dart:11:43)
#1      new DynamicLibrary.open (dart:ffi-patch/ffi_dynamic_library_patch.dart:22:12)
#2      _tryObjectBoxLibFile (package:objectbox/src/native/bindings/bindings.dart:84:29)
#3      loadObjectBoxLib (package:objectbox/src/native/bindings/bindings.dart:101:12)
#4      C (package:objectbox/src/native/bindings/bindings.dart:119:27)
#5      C (package:objectbox/src/native/bindings/bindings.dart)
#6      new Model (package:objectbox/src/native/model.dart:19:31)
#7      new Store (package:objectbox/src/native/store.dart:175:21)
#8      openStore (package:notes/objectbox.g.dart:90:5)
<asynchronous suspension>
#9      initStore (package:notes/store.dart:25:16)
<asynchronous suspension>
#10     main (package:notes/main.dart:10:3)
<asynchronous suspension>
$ ldd build/linux/arm64/debug/bundle/lib/libobjectbox.so 
        linux-vdso.so.1 (0x0000ffff86e80000)
        libdl.so.2 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libdl.so.2 (0x0000ffff86d00000)
        libstdc++.so.6 => not found
        libm.so.6 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libm.so.6 (0x0000ffff86c50000)
        libgcc_s.so.1 => /nix/store/x2f8wiip66lxf6zynscszpm4d990q098-xgcc-12.2.0-libgcc/lib/libgcc_s.so.1 (0x0000ffff86c10000)
        libpthread.so.0 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libpthread.so.0 (0x0000ffff86be0000)
        libc.so.6 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libc.so.6 (0x0000ffff86a30000)
        /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/ld-linux-aarch64.so.1 (0x0000ffff86e43000)
$ LD_LIBRARY_PATH=/nix/store/px2m9rmdcp245j1sdgdrhamlk6ph182b-gcc-12.2.0-lib/lib/ ldd build/linux/arm64/debug/bundle/lib/libobjectbox.so
        linux-vdso.so.1 (0x0000ffff9919b000)
        libdl.so.2 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libdl.so.2 (0x0000ffff99010000)
        libstdc++.so.6 => /nix/store/px2m9rmdcp245j1sdgdrhamlk6ph182b-gcc-12.2.0-lib/lib/libstdc++.so.6 (0x0000ffff98de0000)
        libm.so.6 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libm.so.6 (0x0000ffff98d30000)
        libgcc_s.so.1 => /nix/store/px2m9rmdcp245j1sdgdrhamlk6ph182b-gcc-12.2.0-lib/lib/libgcc_s.so.1 (0x0000ffff98cf0000)
        libpthread.so.0 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libpthread.so.0 (0x0000ffff98cc0000)
        libc.so.6 => /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/libc.so.6 (0x0000ffff98b10000)
        /nix/store/0ckxcm0bnsh64a4vi40d5wjs96i014nl-glibc-2.37-8/lib/ld-linux-aarch64.so.1 (0x0000ffff9915e000)

To fix the issue I tried..

$ LD_LIBRARY_PATH=/nix/store/px2m9rmdcp245j1sdgdrhamlk6ph182b-gcc-12.2.0-lib/lib/ flutter run
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to load dynamic library 'libobjectbox.so': libobjectbox.so: cannot open shared object file: No such file or directory

but it didn't work. I thought that the issue may be with flutter run overriding the LD_LIBRARY_PATH - so I've decided to test it another way:

$ flutter build linux
$ LD_LIBRARY_PATH=/nix/store/px2m9rmdcp245j1sdgdrhamlk6ph182b-gcc-12.2.0-lib/lib/ build/linux/arm64/debug/bundle/notes 
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Failed to load dynamic library 'libobjectbox.so': libobjectbox.so: cannot open shared object file: No such file or directory

But it still doesn't work

greenrobot-team commented 9 months ago

Thanks for reporting!

Failed to load dynamic library 'libobjectbox.so': libobjectbox.so: cannot open shared object file: No such file or directory

This sounds like the shared library isn't bundled at all. It should be in a lib folder next to the executable.

Can you

MrCyjaneK commented 9 months ago

Hey! The lib is at the right place - I've tested it on a just created flutter project. As can be seen in the ldd - the file is there.

My dependencies are exactly the same as in getting started (with latest versions from pub.dev).

greenrobot commented 9 months ago

This could be relevant:

libstdc++.so.6 => not found

We don't test on NixOS, so I'm sorry that we cannot really help here. This is extremely common lib with Linux, so my guess that this is a very NixOS-specific issue. Let us know if you find something out.

MrCyjaneK commented 9 months ago

Okay! I'll investigate that further and let you know about the details!

jordanisaacs commented 9 months ago

I am not familiar with how flutter packaging works, but I packaged the objectbox-c pre-built shared object for nixos (see gist).

I am able to get apps running if I manually delete lib/libobjectstore.so and then symlink in the patched binary from the nix store. However, when I rebuild it seems to get overwritten as the cmake file always re-downloads the prebuilt binary. As I am not familiar with flutter packagingI am not sure best practice for updating the cmake file to allow me to "bring my own shared object."

MrCyjaneK commented 9 months ago

@jordanisaacs I think that a flag for building objectbox as a part of flutter build is they way to go - but I'm unsure what's the objectbox team on that.

greenrobot commented 9 months ago

I don't follow; e.g. what's "the patched binary from the nix store"?

If you do not want the CMake setup, you can e.g. go with download.sh - there's a tab for that in the installation docs. And/or, copy and adjust the CMakeLists.txt for your needs?

MrCyjaneK commented 9 months ago

the patched binary from the nix store is output of the nix expression posted by @jordanisaacs. (p.s. I couldn't get it to work with nix-build).

And I think that I'll speak for me and other nix users who use objectbox - we wouldn't really want to manually adjust the CMakeLists.txt in every project because we are already using objectbox_flutter_libs and it should provide the system system with binary it can run.

MrCyjaneK commented 9 months ago

also I've just realized that objectbox is closed source.. truly a good job at obfuscating that fact.. And since using closed source code is a blocker for me I guess that I'll need to find some other database that doesn't hide the (quite important imo) fact about the project source being unavailable.

MrCyjaneK commented 9 months ago

also since we are here already - could you change licensing on https://pub.dev/packages/objectbox? This is a bit misleading - mentioning that you also accept the objectbox binary license would be a cool thing. p.s. I'm unsubscribing from this issue, so ping me if you need something from me.

jordanisaacs commented 9 months ago

I don't follow; e.g. what's "the patched binary from the nix store"?

If you do not want the CMake setup, you can e.g. go with download.sh - there's a tab for that in the installation docs. And/or, copy and adjust the CMakeLists.txt for your needs?

The issue is NixOS doesn't have its shared libraries in the standard Linux location. Hence you see missing libraries with ldd. that Nix expression I wrote patches your pre-built shared object to point to the other shared objects correctly (using autopatchelf), but it also places it in the nix store /nix/store/*****. Furthermore nix builds software in a sandbox without network access.

I think all I need as a packager is for objectbox to provide an environment variable that skips downloading the shared object in the build phase. My goal is to package BlueBubbles for Nix which utilizes this library, and it would also make life easier packaging anything else that utilizes this library .

greenrobot commented 9 months ago

@jordanisaacs Thanks for providing some background!

Had a quick look... CMake offers providing some "patch command" (docs here, search for "PATCH_COMMAND"). If there would be a way to "inject" (e.g. env var?) a patch command from your side, would you be able to run autopatchelf and do the adjustments? This would also cover updating to a new version and stuff; might be a smoother (more automated) process?