-
Notifications
You must be signed in to change notification settings - Fork 366
Questions about using Cargo to build a Rust library used from C++ #291
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
Comments
You likely still need it. Unless the generated file is empty (which you can check by running the code generator CLI command on the source file, |
Those are not from this crate. You are looking at https://docs.rs/cc/1.0.59/cc/struct.Build.html#method.file and https://docs.rs/cc/1.0.59/cc/struct.Build.html#method.flag_if_supported which are from https://github.com/alexcrichton/cc-rs. We don't pre-add a std flag to the returned cc::Build because if your cxx::bridge module contains an
I believe MSVC defaults to c++14 so this still works. For newer standards you would need to pass a flag formatted as
A cross platform abstraction for compiler flags is outside the scope of this crate. It would be a good thing for somebody to develop (or might already exist; I have not looked) but shouldn't be coupled to the cxx crate. Other forms of building C++ inside build.rs would want that too. |
Line 5 in 2599f88
Line 7 in 2599f88
|
This is a Cargo thing 🙁. If you are able to use a build system that's built to support multi-language builds with C++ code depending on Rust code (Bazel, etc) then you would never deal with this. If you need this to work with Cargo such that a use std::env;
use std::fs;
use std::path::Path;
let out_dir = env::var("OUT_DIR").unwrap();
let staticlib = Path::new(&out_dir).join("libcxxbridge-demo.a");
let put = staticlib
.parent().unwrap()
.parent().unwrap()
.parent().unwrap()
.parent().unwrap()
.join("libcxxbridge-demo.a");
fs::copy(&staticlib, put).unwrap(); |
You can't make or have a std::string by value in Rust because it has a move constructor, which is incompatible with Rust's language level move behavior. For example a small string optimized std::string implementation may rely on internal pointers that need to be repointed during moves. If you need to expose std::string for the public C++ signature, you could make it a wrapper that calls the private bridge signature, where the bridge produces either RustString and the wrapper uses |
Thanks for the answers - very helpful!
This might be a stupid question, but how do I install the
Ah that makes sense. I can't really imagine why a
Yeah I think that is what I will end up doing. I was kind of hoping
That works, I also came up with this, but I'm not sure it is any better (probably won't work with cross compilation):
Thanks for the help! |
For example standard library implementations with the following string layout, which takes advantage of not needing a branch for dereferences of the data pointer.
From #250 (comment), "So far as I know that is indeed something that our standard library does (and even if it didn't, I wouldn't want to guarantee that it wouldn't in future)". |
@Timmmm did you face similar errors in 3. ? |
Doesn't ring a bell, but that looks like you're trying to link two libraries that have each been linked with different versions of Microsoft's Visual C++ Runtime Library (MSVCRT). It comes in a few different flavours - statically/dynamically linked, debug/release, single/multithreaded, etc. I have no idea how that could have happened though sorry! I'd suggest building with all the commands shown (however you do that) and finding the flags that are set to choose which library to use. |
Cargo defaults to MSVC dynamic release by default. by adding in the rustflags = ["-Ctarget-feature=+crt-static"], i was able to get a static build but not sure for a debug build. |
I'm trying to set up a simple Rust library with a C++ interface, based on the
demo
in this repo, using Cargo. I have quite a few questions, hope that's ok:In
build.rs
it passessrc/demo.cc
to the code generator/compiler. If I'm only exposing Rust code to C++, and not the other way around, presumably I only need this if I have custom C++ bridging code, e.g. friendlier wrappers of the shared structs?If I remove these two lines:
then I get C++11 errors, in other words C++11 is always required. But doesn't that mean that the compiler should add
-std=c++11
even if you don't explicitly pass that flag? Also what happens if you're using MSVC? I would have expected an API like.cpp_standard(CppStandard::cxx14)
.I got a basic program working. After many link errors I figured out I have to link with the Rust dynamic library (
libdemo.dylib
) and with the cxxbridge static library (libcxxbridge-demo.a
) and thecxx
library (libcxxbridge04.a
). Can you explain what all those are?libcxxbridge-demo.a
andlibcxxbridge04.a
don't seem to get copied to a canonical location. In other words I have to link withtarget/debug/build/demo-78993d207bfe982b/out/libcxxbridge-demo.a
andtarget/debug/build/cxx-f3cb2e64024d3552/out/libcxxbridge04.a
. That doesn't seem right? I'd have expected them all to be copied or moved totarget/debug/
.If I have a function like this:
fn get_cpp_string() -> CxxString;
it saysreturning C++ string by value is not supported
. Is that a permanent thing? I'd really like the exposed C++ API to use standard C++ types rather thancxx
types because it is a public API rather than something internal. I can't see any reason why you couldn't return astd::string
by value.Thanks!
The text was updated successfully, but these errors were encountered: