简体   繁体   English

Rust linker 错误:链接系统库时使用“-Wl,--as-needed”

[英]Rust linker errors: using "-Wl,--as-needed" when linking system libraries

I'm trying to write an application primarily in rust that uses a gtk-based frontend written in C++. I've gotten pretty far in getting the build setup in Cargo, but it's failing in the linking stage.我正在尝试主要在 rust 中编写一个应用程序,该应用程序使用在 C++ 中编写的基于 gtk 的前端。我在 Cargo 中获得构建设置已经很远了,但它在链接阶段失败了。

I've created a minimal reproducible example.我创建了一个最小的可重现示例。

// build.rs

extern crate cc;
extern crate pkg_config;

fn main() {
    let gtk = pkg_config::probe_library("gtk+-3.0").unwrap();
    cc::Build::new()
        .cpp(true)
        .file("src/gui.cc")
        .includes(gtk.include_paths)
        .compile("gui");
}

// src/gui.cc

// This is essentially the first example from https://docs.gtk.org/gtk3/getting_started.html

#include <gtk/gtk.h>

extern "C" {
int run_gui();
}

static void activate(GtkApplication* app, gpointer) {
  GtkWidget* window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), "Window");
  gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
  gtk_widget_show_all (window);
}

int run_gui() {
  GtkApplication* app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
  g_signal_connect (app, "activate", G_CALLBACK (activate), nullptr);
  int status = g_application_run (G_APPLICATION (app), 0, nullptr);
  g_object_unref (app);

  return status;
}
// src/main.rs

extern "C" { 
    fn run_gui() -> core::ffi::c_int;
}

fn main() {
    unsafe { run_gui(); }
}

When I cargo build the package, compiling the c++ and rust files seems to work fine, but then I get undefined reference errors on the link stage.当我cargo build package 时,编译 c++ 和 rust 文件似乎工作正常,但随后我在链接阶段遇到未定义的引用错误。

/usr/bin/ld: /home/pete/workspaces/csvtk/so-minimal-gtk/target/debug/build/so-minimal-gtk-75c7a9a61d32d2e6/out/libgui.a(gui.o): in function `activate(_GtkApplication*, void*)':
          /home/pete/workspaces/csvtk/so-minimal-gtk/src/gui.cc:9: undefined reference to `gtk_application_window_new'
          /usr/bin/ld: /home/pete/workspaces/csvtk/so-minimal-gtk/src/gui.cc:10: undefined reference to `gtk_window_get_type'
  ...

The link line, which is quite long, is also logged before that error.很长的链接行也在该错误之前记录。 It includes all the required gtk libraries, -lgtk-3 , -lcairo , etc. When I run it outside of cargo, it fails with the same errors, but, when I remove the -Wl,--as-needed flag from the link line, it links correctly and the program runs fine.它包括所有必需的 gtk 库、-lgtk -Wl,--as-needed -lgtk-3-lcairo等。当我在 cargo 之外运行它时,它失败并出现相同的错误,但是,当我从链接线,它链接正确,程序运行良好。

Why did rustc add -Wl,--as-needed ?为什么 rustc 添加 -Wl -Wl,--as-needed Is there a reason those gtk symbols aren't "needed" from the perspective of the linker?从 linker 的角度来看,这些 gtk 符号不是“需要”的原因吗? Any tips on how to fix this problem elegantly?关于如何优雅地解决这个问题的任何提示?

In general, using --as-needed as a flag to the linker is extremely helpful because it prevents your binary from being linked to libraries it doesn't use directly.通常,使用--as-needed作为 linker 的标志非常有用,因为它可以防止您的二进制文件链接到它不直接使用的库。 As an example of a reason why this is beneficial, if you depend on libfoo 1.0, which depends on libbar 1.0, and later on libfoo 1.1 updates to libbar 2.0, then as long as you don't use libbar directly, your code will continue to work with --as-needed , but won't work without it (unless libbar has symbol versioning).举例说明为什么这是有益的,如果你依赖 libfoo 1.0,它依赖于 libbar 1.0,后来 libfoo 1.1 更新到 libbar 2.0,那么只要你不直接使用 libbar,你的代码就会继续与--as-needed一起工作,但没有它就无法工作(除非 libbar 有符号版本控制)。

The kind of impact is visible here when you use objdump -x on the binary after making the change I suggest below:当您在进行我在下面建议的更改后对二进制文件使用objdump -x时,这种影响在这里是可见的:

  NEEDED               libgtk-3.so.0
  NEEDED               libgio-2.0.so.0
  NEEDED               libgobject-2.0.so.0
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.6
  NEEDED               ld-linux-x86-64.so.2

ldd lists 70 libraries linked into your program, and you're only directly requiring to 6, including the dynamic linker. ldd列出了 70 个链接到您的程序的库,您只需要直接要求 6 个,包括动态的 linker。

You can usually rely on other crates to specify their link dependencies correctly.您通常可以依靠其他 crate 来正确指定它们的链接依赖项。 However, you need to be careful because when you're creating your own dependency on a library using C or C++, you have to specify the libraries to link with yourself.但是,您需要小心,因为当您使用 C 或 C++ 创建自己对库的依赖项时,您必须指定要与自己链接的库。 This can be seen if you use cargo build -v , where you can notice that your gui library is linked after the dependencies of libgtk-3:如果您使用cargo build -v可以看到这一点,您可以注意到您的gui库链接libgtk-3 的依赖项之后:

Running `rustc --crate-name test_repo --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=c60f7e6ab8348a08 -C extra-filename=-c60f7e6ab8348a08 --out-dir /tmp/user/1000/test-repo/target/debug/deps -C incremental=/tmp/user/1000/test-repo/target/debug/incremental -L dependency=/tmp/user/1000/test-repo/target/debug/deps -L native=/usr/lib/x86_64-linux-gnu -L native=/tmp/user/1000/test-repo/target/debug/build/test-repo-c89dae0927f2103a/out -l gtk-3 -l gdk-3 -l z -l pangocairo-1.0 -l pango-1.0 -l harfbuzz -l atk-1.0 -l cairo-gobject -l cairo -l gdk_pixbuf-2.0 -l gio-2.0 -l gobject-2.0 -l glib-2.0 -l static=gui -l stdc++`

So you'd want to do something more like this in your build.rs :所以你想在你的build.rs中做更多类似的事情:

// build.rs

extern crate cc;
extern crate pkg_config;

fn main() {
    let gtk = pkg_config::probe_library("gtk+-3.0").unwrap();
    cc::Build::new()
        .cpp(true)
        .file("src/gui.cc")
        .includes(gtk.include_paths)
        .compile("gui");
    for path in gtk.link_paths {
        println!("cargo:rustc-link-search={}", path.display());
    }
    for lib in gtk.libs {
        println!("cargo:rustc-link-lib={}", lib);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在与Rust中的本机库链接时,将符号公开给动态链接器 - Expose symbols to dynamic linker when linking with native library in Rust 将 Rust 应用程序与不在运行时的动态库链接 linker 搜索路径 - Linking Rust application with a dynamic library not in the runtime linker search path 使用 clion 调试 rust 时,如何修复奇怪的非 ascii 字符动态 linker 错误? - How can I fix weird non-ascii character dynamic linker errors when debugging rust with clion? 使用clang与C链接时缺少Rust对象文件 - Rust object file missing when linking with C using clang 在Rust中指定到FFI库的链接路径有哪些不同的方法? - What are the different ways of specifying the linking path to FFI libraries in Rust? 交叉编译错误`ld:未知选项:--as-needed` - Cross compile error `ld: unknown option: --as-needed` 链接静态 C 库时 Rust 缺少库 - Rust missing libraries while linking static C libraary 错误:使用cargo从windows交叉编译一个rust项目到linux时“找不到链接器‘cc’” - Error: “linker 'cc' not found” when cross compiling a rust project from windows to linux using cargo Rust 和 Flamegraph:使用货物安装时出现一堆错误 - Rust and Flamegraph: Bunch of errors when installing using cargo 使用LD.LLD链接Rust二进制文件 - Linking Rust binary using LD.LLD
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM