dtolnay / cxx

Safe interop between Rust and C++
https://cxx.rs
Apache License 2.0
5.81k stars 330 forks source link

Demo or Example of utilizing 3rd party libs (via Conan ideally) #1129

Closed EMCP closed 1 year ago

EMCP commented 1 year ago

I am brand new to rust.. coming from C++.. and I'd packaged a 3rd party library via conanrecipe.py ... I now want to switch from using that in C++ to Rust (via CXX I guess) .. My question is to confirm if I am going down the right way.. basically ConanRS provides some of the mechanism to pull in the conan package.. but now I need to learn how to reference those header files and .a / .so files in my rust C++ code..

based on some questions to conanrs https://github.com/Devolutions/conan-rs/issues/11 .. I will read the build info metadata .. something like

build.rs


use std::path::Path;
use std::env;

use conan::*;

fn main() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    let conan_profile = format!("{}-{}", target_os, target_arch);

    let command = InstallCommandBuilder::new()
        .with_profile(&conan_profile)
        .build_policy(BuildPolicy::Missing)
        .recipe_path(Path::new("conanfile.txt"))
        .build();

    if let Some(build_info) = command.generate() {
        println!("using conan build info");
        build_info.cargo_emit();

        // Take the info and pipe it to CXX somehow

        let mycustomconanpkg = build_info.get_dependency('mycustomconanpkg')

        let mycustomconanpkg_dir = mycustomconanpkg.get_root_dir().unwrap();
        let mycustomconanpkg_lib_dir = mycustomconanpkg.get_library_dir().unwrap();
        let mycustomconanpkg_inc_dir = mycustomconanpkg.get_include_dir().unwrap();

 ....
    // IT IS HERE I will ADD the .h files from the conan package.. but what about the .so/.a files ? 

instructions - https://cxx.rs/build/cargo.html#header-include-paths

 ....    
        cxx_build::bridge("src/main.rs")
        .file("src/blobstore.cc")
        .flag_if_supported("-std=c++14")
        .compile("cxxbridge-demo");

        println!("cargo:rerun-if-changed=src/main.rs");
        println!("cargo:rerun-if-changed=src/blobstore.cc");
        println!("cargo:rerun-if-changed=include/blobstore.h");       
    }
}

I worry that even if I bring in the code via conan... I will still need to write a .cpp and .h file to reference those third parties AND bring in the Rust bits.. like I saw in here

https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h#L2

and

https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc#L2

Am I going in the right direction in order to use conan based code in CXX ? it will need some bridge code which references the .h files from the mycustomconanpkg

EMCP commented 1 year ago

I guess the main part of the docs I am after is this

https://cxx.rs/build/cargo.html#including-headers-from-dependencies

"You get to include headers from your dependencies, both handwritten ones contained as .h files in their Cargo package, as well as CXX-generated ones."

instead of my code being handwritten tho.. it's brought in from a 3rd party.. right? but I need to add those header paths still .. and reference them somehow

`#include "dependencycratename/path/to/their/header.h`` won't work since there is not "crate" in my case.. only conan.. right?

EMCP commented 1 year ago

okay i can successfully reference things

Here's what I had to do

https://docs.rs/cxx-build/latest/cxx_build/static.CFG.html#cfgexported_header_dirs

build.rs

    if let Some(build_info) = command.generate() {
        println!("using conan build info");
        build_info.cargo_emit();

        let twsapi = build_info.get_dependency("twsapi").unwrap();
        let twsapi_inc_dir = twsapi.get_include_dir().unwrap();

        let twsapi_inc_dir_path = Path::new(twsapi_inc_dir);
        CFG.exported_header_dirs.extend([twsapi_inc_dir_path]);    <------- key line is here.. adding the include path

        cxx_build::bridge("src/main.rs")
            .file("src/blobstore.cc")
            .flag_if_supported("-std=c++17")
            .compile("cxxbridge-demo");
    }

then.. just to test in blobstore.cc , I can successfully build

#include "rust_twsapi_demo/include/blobstore.h"
#include "rust_twsapi_demo/src/main.rs.h"
#include <algorithm>
#include <functional>
#include <set>
#include <string>
#include <unordered_map>

#include "Contract.h"  <------ from the conan installed lib
EMCP commented 1 year ago

My final question is.. how can I test or ensure that I've included not just the includes/ but the lib dir ?

image

EDIT : looks like I need to print out in the build something like

cargo:rustc-link-lib=<path_to_lib>

? I will give this a try and if it works close out

Looks like ConanRS took care of this already ! NICE!

...
[rust_twsapi_demo 0.1.0] conanfile.txt: Generated graphinfo
[rust_twsapi_demo 0.1.0] using conan build info
[rust_twsapi_demo 0.1.0] cargo:rustc-link-search=native=/home/emcp/.conan/data/twsapi/10.17.01/stonks/prod/package/062863c92a5a0a247840166e9f84ebe8d10786b9/lib
[rust_twsapi_demo 0.1.0] cargo:rustc-link-lib=twsapi

...