CXX Noob with simple hello world not finding my Library function

I have quite a complicated project involving C++ library coming from an external source.. I have added onto it a Conan Recipe thankfully.. to sort of time the thing.. but now want to try my hand at bringing this C++ lib into a rust version of the project.. however

CXX never seems to find my functions.. I've reduced things to a basic hello world C++ function but getting a linking error.. Any help getting this just to compile/build.. and maybe even print helloworld from a C++ function would be a great help. thanks

cargo.toml

[package]
name = "twsapi_helloworld"
version = "0.1.0"
edition = "2021"
publish = false
links = "twsapi"

[dependencies]
cxx = "1.0.107"

[build-dependencies]
cxx-build = "1.0.107"
conan = "0.3.0"

Build.rs

use std::path::Path;
use std::env;
use cxx_build::CFG;
use conan::*;

fn main() {
    // requires : sudo apt install libintelrdfpmath-dev
    println!("cargo:rustc-link-lib=bidgcc000");

    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    let default_conan_profile = "default";
    let _conan_profile = format!("{}-{}", target_os, target_arch);

    let command: InstallCommand = InstallCommandBuilder::new()
        .with_profile(&default_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();

        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);
        // Add TWSAPI Conan Pkg to Includes
        CFG.exported_header_dirs.extend([twsapi_inc_dir_path]);

        cxx_build::bridge("src/main.rs")
            .file("src/gettingstarted.cpp")
            .flag_if_supported("-std=c++17")
            .compile("twsapi_helloworld");
    }

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

Main.rs


#[cxx::bridge]
mod ffi {
    unsafe extern "C++" {
        include!("twsapi_helloworld/include/gettingstarted.h");
        fn sayHello();
    }
}

fn main() {
    ffi::sayHello();
}

gettingstarted.cpp

#include <iostream>
#include "gettingstarted.h"

void sayHello() {
    std::cout << "Hello, World!" << std::endl;
}

gettingstarted.h

#ifndef BOOTSTRAP_RUST_CPP_CONAN_GETTINGSTARTED_H
#define BOOTSTRAP_RUST_CPP_CONAN_GETTINGSTARTED_H

void sayHello(); // Declaration of the sayHello function

#endif //BOOTSTRAP_RUST_CPP_CONAN_GETTINGSTARTED_H

The Error

error: linking with `cc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/emcp/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" VSLANG="1033" "cc" "-m64" "/tmp/rustcqMfEoy/symbols.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.1a2zomsxguieaumg.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.30qajbg5fjaj3tr6.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.3etk40n172eaeloe.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.3jt5wmqsox99u2uz.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.4l9lrrzeqgs06mql.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.kndqjgmeyza84ln.rcgu.o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.2qak7sfvj3n6xry3.rcgu.o" "-Wl,--as-needed" "-L" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps" "-L" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/build/cxx-fe2d09253ef296a2/out" "-L" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/build/link-cplusplus-eca67613d27303d0/out" "-L" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bdynamic" "-lbidgcc000" "-Wl,-Bstatic" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/libcxx-62c8e680a0563793.rlib" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/liblink_cplusplus-af56f3957e701a97.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-8f88c761e33f2651.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-f9018f9cee1cc5ff.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-919f89587cbed68d.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-c6624cb4360306cd.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-4930b3dc482158f7.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-65bea4bb6af40828.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-bc6864da821ce9a2.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-1bccb7a942e1b311.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-356231f77d1e268a.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-80ed5799bf463787.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-9c3df673b2797081.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-c6afbee8d1102512.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-682387162b570769.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-05a2cedbb78c1d4f.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-f002c8f83a289c4b.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-649be05783c8912e.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-13da980d6c74fec5.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-46a989d0e2cef827.rlib" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-b114db70ea0690b1.rlib" "-Wl,-Bdynamic" "-lstdc++" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/emcp/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: /usr/bin/ld: /home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/target/debug/deps/twsapi_helloworld-4a43251fb54e8cb5.1a2zomsxguieaumg.rcgu.o: in function `twsapi_helloworld::ffi::sayHello':
          /home/emcp/Dev/git/Bootstrap/bootstrap-rust-cpp-conan/src/main.rs:9: undefined reference to `cxxbridge1$sayHello'
          collect2: error: ld returned 1 exit status
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)


okay the issue was sort of simple.. BUT .. after a little bit of rereading the CXX documentation.. I noticed the CXX bridge was in the top of the function.. and having it in that if let Some() part of build.rs got me worried that it was not getting called..

lo and behold when I moved the CXX parts out .. it compiles and built a helloworld from C++!! sweet!

...
    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);
        // Add TWSAPI Conan Pkg to Includes
        CFG.exported_header_dirs.extend([twsapi_inc_dir_path]);

     
    }

   cxx_build::bridge("src/main.rs")
            .file("src/gettingstarted.cpp")
            .flag_if_supported("-std=c++17")
            .compile("twsapi_helloworld");
    println!("cargo:rerun-if-changed=src/main.rs");
    println!("cargo:rerun-if-changed=src/gettingstarted.cpp");
    println!("cargo:rerun-if-changed=include/gettingstarted.h");
}

One question I still have is .. why does the official example in CXX use a file ending in .cc instead of .cpp ??

AFAIK, .cpp, .cxx and .cc are all commonly used file suffixes for C++ files.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.