3

I have written a C++ library with a C wrapper and want to call those functions from my Rust project. However, when I try to link my Rust project to the C library, I get a long error with the note

  note: /usr/bin/ld: cannot find -l../cpp_library/build/libdisplay.so

I have tried passing an absolute path to the library and received a similar error.

My combined project has the following directory and contents

├── cpp_library
│   ├── CMakeLists.txt
│   ├── include
│   │   └── display.h
│   └── src
│       ├── display.cpp
│       └── main.cpp
└── rust_project
    ├── build.rs
    ├── Cargo.lock
    ├── Cargo.toml
    ├── src
       └── main.rs

CMakeLists.txt

cmake_minimum_required(VERSION 3.1.0)
project(directory_test)
set(CMAKE_BUILD_TYPE Release)

#Bring the headers into the project
include_directories(include)


set(SOURCES "src/display.cpp")

#Generate the shared library from the sources
add_library(display SHARED ${SOURCES})
add_executable(display_test "src/main.cpp" ${SOURCES})

display.h

extern "C" {
    void display();
}

display.cpp

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

void display(){
    std::cout << "A C++ println" << std::endl;
}

main.cpp

#include "display.h"

int main() {
    display();
}

build.rs

fn main() {
    println!("cargo:rustc-link-search=../cpp_library/build/");
    println!("cargo:rustc-link-lib=../cpp_library/build/libdisplay.so");
}

main.rs

extern {
    fn display();
}

fn main() {
    println!("Hello, world!");
    unsafe {
        display();
    }
}

You can also see the project on Github.

I build the C library with

cd cpp_library
mkdir build
cd build
cmake ..
make

When I build the Rust project, I get the error shown above.

How am I supposed to link the C library to the Rust project?

Update 1

The posts How do I specify the linker path in Rust? and Where should I place a static library so I can link it with a Rust program? indicate how to add a directory to the library search path and link a library. I have tried these solutions, but still receive the error mentioned above.

Following the advice of Linking Rust application with a dynamic library not in the runtime linker search path, I compiled the rust project with

cargo rustc -- -C link-args='-Wl,-rpath,$ORIGIN/../../../cpp_library/build/'

but received the same error. I also tried passing an absolute path and received the same result.

I removed the redundant #[link(name = "display")], but this did not resolve the problem.

pdiffley
  • 603
  • 9
  • 18
  • It looks like your question might be answered by the answers of [How do I specify the linker path in Rust?](https://stackoverflow.com/q/40833078/155423); [Linking Rust application with a dynamic library not in the runtime linker search path](https://stackoverflow.com/q/40602708/155423); [Where should I place a static library so I can link it with a Rust program?](https://stackoverflow.com/q/43826572/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Apr 07 '20 at 02:34
  • 1
    The duplicates applied to your project and your build instructions (no "build" directory is created): `println!("cargo:rustc-link-search=../cpp_library/"); println!("cargo:rustc-link-lib=dylib=display");` – Shepmaster Apr 07 '20 at 02:41
  • Either `#[link(name = "display")]` or `cargo:rustc-link-lib` should be used, not both. – Shepmaster Apr 07 '20 at 02:44
  • I tested the solutions given in the potential duplicates, but still receive the same error. I edited the instructions for building the c library so that the library ends up in the right place. I removed the redundant `#[link(name = "display")]` but that did not resolve the problem. – pdiffley Apr 07 '20 at 17:43
  • I cloned your repository and made [the changes I suggested](https://stackoverflow.com/questions/61071884/how-to-call-a-shared-library-in-rust#comment108044807_61071884) and the code compiled. – Shepmaster Apr 07 '20 at 17:49
  • Perhaps you are trying to *run* the program, which requires that you set `LD_LIBRARY_PATH` (or OS-appropriate equivalent). `LD_LIBRARY_PATH=$PWD/../cpp_library/ cargo run` -> `Hello, world! A C++ println`. See also [How can I type “cargo run” without needing to set the LD_LIBRARY_PATH shell variable?](https://stackoverflow.com/q/51796417/155423) – Shepmaster Apr 07 '20 at 17:53
  • *but still receive the same error* — then you did **not** apply the changes. Your error specifically says: `note: /usr/bin/ld: cannot find -l../cpp_library/build/libdisplay.so`. That argument should not have a path in it, only the library name. That's why [the changes](https://stackoverflow.com/questions/61071884/how-to-call-a-shared-library-in-rust#comment108044807_61071884) include two line of change; one setting the path and one setting the name of the library. – Shepmaster Apr 07 '20 at 17:55
  • 1
    Oh, I see. I missed the edit to the second line of build.rs. After applying your changes, I am able to build successfully. Originally, I was not trying to run the program, but you did anticipate the next problem I was going to have. With the edit to LD_LIBRARY_PATH, I am able to run the program successfully. Thank you so much for your help! – pdiffley Apr 07 '20 at 19:51

0 Answers0