Description
TL;DR:
I've needed to hack my generated .cc
files to change:
extern "C" {
void base$cxxbridge03$log_string(::rust::Str::Repr msg) noexcept {
void (*log_string$)(::rust::Str) = log_string;
log_string$(msg);
}
} // extern "C"
to
extern "C" {
__attribute__((visibility("default"))) void base$cxxbridge03$log_string(::rust::Str::Repr msg) noexcept {
void (*log_string$)(::rust::Str) = log_string;
log_string$(msg);
}
I would like to add the ability to do that, possibly with an additional parameter to the cxx::bridge
macro alongside the existing namespace
parameter.
Here's why.
Our final build products are:
- C++ library
libservices.so
. This C++ depends upon APIs exported from... - C++ library
libbase.so
Each contains a blob of Rust code:
- Rust rlib
librust_services.rlib
- Rust rlib
librust_base.rlib
librust_services.rlib
uses APIs exported publicly by librust_base.rlib
. Specifically, the code in librust_services.rlib
uses a log()
API within librust_base.rlib
, which in turn uses native code within the rest of libbase.so
.
The only officially approved way to make these C++ binaries is by generating two Rust staticlib
s:
- Rust staticlib
libservices_rust_deps.a
- Rust staticlib
libbase_rust_deps.a
and then linking them into the .so files with all the rest of the C++ code.
So we hope to achieve this call stack:
- Rust code in
librust_services.rlib
(which gets built intolibservices.so
). It calls - Rust code in
librust_base.rlib
, which calls - Native code elsewhere in
libbase.so
So, where should the code in librust_base.rlib
end up? Specifically this log()
Rust API?
Ideally, that Rust API would only be in libbase.so
and so the Rust code within libservices.so
would call other Rust code in libbase.so
. But as far as I know, that's impossible. Rust doesn't provide a way to mark Rust code as exported from a staticlib
- there is no equivalent to the C directive __attribute__((visibility("default")))
. (Again, as far as I understand it) Rust will only attempt to keep C-facing APIs marked with #[no_mangle]
directive; there's no way to ask that a given Rust API is exported from a .so
which is downstream of a staticlib
. (Maybe this merits an issue filed against rust - I'd be interested in opinions - this conflation of exporting vs naming seems to cause trouble now and again, e.g. rust-lang/rust#54135 (comment)).
Given that we can't export the Rust log()
API from libbase.so
, we need to build the Rust code into libservices.so
. But now the Rust code has to depend upon the C++ implementations, which means we need to export them from libbase.so
. Hence - the need for the generated C++ code to export the symbols from libbase.so
.
Would you accept a PR to add this exporting ability?