-
Notifications
You must be signed in to change notification settings - Fork 42
Set library version with SDK language #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set library version with SDK language #288
Conversation
.github/workflows/c_cpp.yml
Outdated
- name: Build C library for ${{ matrix.target }} | ||
env: | ||
FOXGLOVE_SDK_LANGUAGE: c | ||
run: cargo build --release | ||
working-directory: c | ||
- name: Ensure generated files are up to date | ||
run: git diff --exit-code | ||
|
||
- name: Build C++ library and run tests | ||
if: ${{ !fromJson(matrix.cross) }} | ||
env: | ||
FOXGLOVE_SDK_LANGUAGE: cpp | ||
run: make test | ||
working-directory: cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is going to work – the C++ sdk is just a wrapper for better ergonomics of calling the C sdk. The user will link the C sdk with their program and use the wrappers to call functions from it. So there is not really a "separate" build of the two SDKs (we aren't currently planning to ship a prebuilt C++ library, only C)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As for alternatives, some ideas:
- If this is used in specific places (like websocket server & mcap writer), the c++ sdk wrappers could pass in some value when creating those to override the defaults (but we'd have to remember to do this in every relevant location)
- We could add a global function to set the library name at runtime (though would have to decide when to call it? might end up being pretty horrendous to do this in a cross-platform way, unless we want to make the users just call some init function explicitly)
- I really hope someone else can come up with a better 3rd option 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I completely missed that this step doesn't run cargo build. Runtime it is.
I thought about something similar to the second idea; in python, it seems reasonable for us to call a function during the module initialization. I'll see if I can find something that seems workable across the board.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm leaning towards a hybrid approach: introduce a compiled_sdk_language
build-time environment variable to replace what's here, and then have a static init step in c++ which can override this. Then at runtime, build a string with the compiled version. That sidesteps the cross-platform issue you linked, and I'd like to avoid providing something in the API to set the library name / language directly.
When I tried this out, I get a cmake error — something internal to Catch2 — unless I skip building the tests. I'll have to solve whatever issue that is (assuming it's not uncovering a legitimate problem), but would like your thoughts on the approach before spending more time on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I'm not sure what you mean by a static init step, you mean just forcing the user to call something like foxglove::initSDK()? I guess that's fine. We could also call it ourselves each time a Channel is constructed, as an example
also, for the Catch2 issue, maybe try rebasing - I fixed something related to that recently but it was a linker error, not a cmake error, so maybe different from what you ran into
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another alternative is that we could simply accept that we only have one string which is used for both C/C++ SDKs. Then assume probably 99%+ of users would be using it via C++. I guess it depends exactly what problem we are trying to solve here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I'm not sure what the cmake error was, but it eventually went away after commenting/uncommenting things in the file (maybe something cached?). Initially I was thinking I could statically initialize something inside an unnamed namespace to take care of this, but I think that was misguided.
I updated to make the calls in the writer & server constructors.
simply accept that we only have one string which is used for both C/C++
This is somewhat user-facing in that it ends up as the 'library' of mcap files, so I think picking either one of those could seem strange. Maybe there's some other name we can use to suggest 'either', but I think I prefer dealing with it at runtime.
The main drawback to me is having this C function around that doesn't have any use for end users.
aa45717
to
779bf58
Compare
c/src/lib.rs
Outdated
@@ -441,6 +441,12 @@ pub unsafe extern "C" fn foxglove_channel_log( | |||
); | |||
} | |||
|
|||
/// For use by the C++ SDK. Identifies that wrapper as the source of logs. | |||
#[unsafe(no_mangle)] | |||
pub extern "C" fn _register_cpp_wrapper() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the leading underscore is technically not allowed in C/C++ https://devblogs.microsoft.com/oldnewthing/20230109-00/?p=107685 (Maybe trailing underscore is ok? or use "internal" in the name?)
I also would recommend including "foxglove" somewhere in the name
.github/workflows/c_cpp.yml
Outdated
env: | ||
FOXGLOVE_SDK_LANGUAGE: cpp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe this can be removed now?
rust/foxglove/src/library_version.rs
Outdated
//! Provides an identifier for the library used as a log source. | ||
use std::sync::OnceLock; | ||
|
||
use crate::SDK_LANGUAGE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I find it a bit confusing that these two things are defined in different files, but they seem quite related
rust/foxglove/src/lib.rs
Outdated
@@ -194,6 +198,12 @@ pub use sink::{Sink, SinkId}; | |||
pub(crate) use time::nanoseconds_since_epoch; | |||
pub use websocket_server::{WebSocketServer, WebSocketServerBlockingHandle, WebSocketServerHandle}; | |||
|
|||
pub(crate) static SDK_LANGUAGE: LazyLock<String> = LazyLock::new(|| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider naming this with "build"/"compile" somewhere in the name to indicate it was set at compile time?
Does this need to be LazyLock? It looks like it is read-only after creation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the name. LazyLock (or something like it) is needed because the unwrapping happens at runtime. I didn't see a way to define a default env var for the build, so would like to keep it optional.
rust/foxglove/src/library_version.rs
Outdated
|
||
/// Returns an identifer for this library, for use in log sinks. | ||
pub(crate) fn get_library_version() -> String { | ||
let language = CELL.get_or_init(|| SDK_LANGUAGE.as_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I guess this means if get_library_version is called before set_sdk_language, then the latter will have no effect? That's probably fine, but wonder if it should be called out in the comments
…ections-with-library-version
Changelog
The SDK language is now reflected in the
library
written to MCAP files, and is included inserverInfo
metadata under the keyfg-library
.Description
Example:
foxglove-sdk-python/v0.3.0
.The language name is set at build time, based on environment. For C++, which is a wrapper around the C library, a function is called by the log sinks when they're created to override that language.
The app may use the serverInfo metadata for troubleshooting or performance analysis. Foxglove has some precedent for the "fg-" prefix in user agents and HTTP header keys. "fg-library" echoes the "library" header of mcap.