corrosion-rs / corrosion

Marrying Rust and CMake - Easy Rust and C/C++ Integration!
https://corrosion-rs.github.io/corrosion/
MIT License
1.07k stars 103 forks source link

Docs: CMake Usage Questions #186

Closed amunra closed 2 years ago

amunra commented 2 years ago

Hello,

I've just started using corrosion for a project and it's pretty neat. I had a few questions that I couldn't find answers to in the docs.

Sorry for posting this as an issue, but I didn't find a user forum or similar.

Exporting Header in CMake

My rust crate exposes a .h C header file. Is this the recommended way of associating it to target exported by corrosion?

# CMakeLists.txt
corrosion_import_crate(
    MANIFEST_PATH Cargo.toml
    FEATURES ffi)
target_include_directories(
    questdb_client INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/include)

Selecting Linkage for target in CMake

My rust library is building both static and dynamic libraries.

# Cargo.toml
[lib]
name = "questdb_client"
crate-type = ["cdylib", "staticlib"]

From CMake, how do I specify for a target to link to either the static or the dynamic lib explicitly?

Thanks!

jschwe commented 2 years ago

Hi,

Sorry for posting this as an issue, but I didn't find a user forum or similar.

That's perfectly fine. I went ahead and opened the Github discussions section for corrosion, so in the future I guess such questions could be asked there.

My rust crate exposes a .h C header file. Is this the recommended way of associating it to target exported by corrosion?

I think this solution is fine. I don't think we really have a recommended way.

From CMake, how do I specify for a target to link to either the static or the dynamic lib explicitly?

I haven't done this before, but I think this is actually answered in the Readme here: https://github.com/corrosion-rs/corrosion/#importing-c-style-libraries-written-in-rust :

In addition to "staticlib", you can also use "cdylib". In fact, you can define both with a single crate and switch between which is used using the standard BUILD_SHARED_LIBS variable.

But this is a global option, so if you want different behaviour per target, then I think this is currently not possible with corrosion. You could try directly linking the actual targets (<library_name>-shared and <library_name>-static ), but I think you would be losing some properties that corrosion only sets on the INTERFACE target that we expose to the user, so this would probably not work out of the box.

KOLANICH commented 2 years ago

I wonder if it is possible to use Rust code in C++ fashion, I mean find_package for discovering prebuilt shared libs installed into the system and their "headers" (which are not quite headers) and target_link_libraries to link them to a lib/binary and add their headers dirs to compiler path. I mean I want to avoid version pinning, dependencies recompilation and static linking and so on, and want libs being linked like C libs are linked: one just updates a binary package and all the apps use the newest version of the lib without any recompilation. Also the possibility of breakage because of Rust stdlib version change is out of scope, it is distro that takes care of all the components of the distro being compatible to each other.

ogoffart commented 2 years ago

@KOLANICH this is a bit out of topic of this particular issue, a separate discussion thread would have been better.

But to answer your question, it is indeed possible to create cmake config files that can be installed along with the binary of a rust-build library, and you can do that with corrosion by simply installing the generated target.

This is what we are doing in Slint: https://github.com/slint-ui/slint/blob/4f5986167b7c1fbfd9dbff842964ca2b74356e8b/api/cpp/CMakeLists.txt#L178

the possibility of breakage because of Rust stdlib version change is out of scope, it is distro that takes care of all the components of the distro being compatible to each other.

It is out of scope for a different reason: every rust library is statically linked and bring its own stdlib that can be mixed. The only ABI surface is with extern "C" and #[repr(C)] things which do have a stable ABI.

Now, i'm closing this issue because the initial question of this issue has been answered. Further comments can go in a separate discussion.