couchbase / couchbase-lite-C

C language bindings for the Couchbase Lite embedded NoSQL database engine
Apache License 2.0
117 stars 37 forks source link

Working on Rust bindings: missing static library dependencies #511

Closed jwhear closed 11 months ago

jwhear commented 11 months ago

Background

I am attempting to develop Rust bindings and wrapper for this project. I am aware of https://github.com/Dushistov/couchbase-lite-rust, however that binding uses couchbase-lite-core directly and does not expose key CBL features like collections. I assume there are some historical reasons for this and thought I'd try developing against the presumably more stable C API.

At this point I have a build.rs script that autogenerates bindings that compile successfully and automated CMake builds of couchbase-lite-C itself. However, when I actually try to build my Rust test suite I end up with a bunch of linker errors.

Issue 1: missing Fleece symbols

A large number of the linker errors are undefined references to various parts of the Fleece API. Examining the existing Rust bindings, it looks like I need to link libFleeceStatic.a but using find build -name 'libFleeceStatic.a' produces no results. After exploring a bit, I discovered that there is a Make target for FleeceStatic that produces it. As a hack, my build script now invokes this make target after running the CMake build.

Is there a reason that CMake with the all target doesn't produce FleeceStatic?

Issue 2: missing BLIP symbols

After "manually" producing the FleeceStatic library and adding it to my linker flags, I now get a bunch of undefined references to various BLIP symbols, example:

ebSocket.a(Worker.cc.o): in function `litecore::repl::Worker::gotError(litecore::blip::MessageIn const*)':
          Worker.cc:(.text+0x15c8): undefined reference to `litecore::blip::MessageIn::getError() const'

I've tried going into the build/vendor/couchbase-lite-core/Networking/BLIP directory and looking for any make targets that might be helpful, but it looks like it simply knows how to build the object files. So this is where I'm stuck currently.

How do I produce BLIPStatic?

It feels like I'm pretty close with this effort, so any help getting unstuck is appreciated.

jwhear commented 11 months ago

Update: I've taken the approach of linking as little as possible and building my way up. Issue 1 is still valid (I have to specifically build FleeceStatic), but I've learned that I shouldn't link both LiteCoreStatic and LiteCoreWebSocket.

With these libraries linked:

    CouchbaseSqlite3
    LiteCoreWebSocket
    FleeceStatic
    mbedcrypto
    mbedtls
    z
    stdc++

here are the symbols I'm still missing:

litecore::websocket::WSLogDomain
litecore::actor::Timer::~Timer()
litecore::actor::Timer::manager()
litecore::actor::Timer::Manager::unschedule(litecore::actor::Timer*, bool)
litecore::actor::Timer::manager()
litecore::actor::Timer::Manager::setFireTime(litecore::actor::Timer*, std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1l, 1000000000l> > >, bool)
pasin commented 11 months ago

What cblite target are you linking to when building with CBL?

jwhear commented 11 months ago

What cblite target are you linking to when building with CBL?

cblite-static

pasin commented 11 months ago

You will need to link with these target objects as well in your CMake similar to https://github.com/couchbase/couchbase-lite-C/blob/master/CMakeLists.txt#L186-L189.

LiteCoreWebSocket FleeceObjects BLIPObjects LiteCoreObjects (I'm a bit puzzled if you will need this or not but I think you don't need to).

jwhear commented 11 months ago

As a hack I've already found the object files that contain the missing symbols and added this to my build.rs:

    //HACK!
    println!("cargo:rustc-link-arg={}/Networking/BLIP/CMakeFiles/BLIPObjects.dir/__/__/LiteCore/Support/Timer.cc.o", vendor_build_dir.to_string_lossy());
    println!("cargo:rustc-link-arg={}/Networking/BLIP/CMakeFiles/BLIPObjects.dir/__/WebSockets/WebSocketInterface.cc.o", vendor_build_dir.to_string_lossy());

This does resolve the linker errors, but it seems pretty dirty to have to reach into the cmake cache files and grab out object files to feed the linker.

pasin commented 11 months ago

Those two files are under BLIPObjects target. So I guessed you are prebuilding CBL-C in a separate step?

Currently, CBL-C CMake only links everything (LiteCore / Fleece / BLIP) together in the cblite dynamic library. The cblite-static only contains CBL-C & LiteCore but not Fleece and BLIP. It becomes hard to link with cblite-static as I don't think we have produced a static lib for BLIP in LiteCore's CMake. If you need this, you may submit a ticket to the LiteCore repro to see if it's possible or not.

jwhear commented 11 months ago

I just tried switching to using dynamic linking; everything just worked and I was able to simplify the sys crate build script substantially. I guess this is the way.