使用Cygwin在Rust应用程序中链接NTDLL,同时定位x86_64-pc-windows-gnu

时间:2017-12-10 23:13:53

标签: rust cygwin gnu

我在DarkEld3r's os_info repository中打开了一个拉取请求,以检索实际的Windows版本和版本名称。

应用程序需要链接到ntdll.dll才能使用RtlGetVersion()。当使用Cygwin和普通的Windows控制台将目标设置为x86_64-pc-windows-msvc时,DLL会正确链接。当目标为x86_64-pc-windows-gnu时,the linker returns an error

   Running `rustc --crate-name print_version examples\print_version.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=ec9720acb7c740b3 -C extra-filename=-ec9720acb7c740b3 --out-dir C:\projects\os-info\target\debug\examples -L dependency=C:\projects\os-info\target\debug\deps --extern kernel32=C:\projects\os-info\target\debug\deps\libkernel32-beacffc979f26c46.rlib --extern user32=C:\projects\os-info\target\debug\deps\libuser32-fbb28ae30109687c.rlib --extern winapi=C:\projects\os-info\target\debug\deps\libwinapi-bb7af3f2a31ea235.rlib --extern os_info=C:\projects\os-info\target\debug\deps\libos_info-c5887b186deb8679.rlib`
error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-m64" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\crt2.o" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version0.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version1.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version10.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version11.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version12.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version2.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version3.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version4.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version5.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version6.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version7.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version8.rust-cgu.o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.print_version9.rust-cgu.o" "-o" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.exe" "C:\\projects\\os-info\\target\\debug\\examples\\print_version-ec9720acb7c740b3.crate.allocator.rust-cgu.o" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "C:\\projects\\os-info\\target\\debug\\deps" "-L" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib" "-Wl,-Bstatic" "C:\\projects\\os-info\\target\\debug\\deps\\libos_info-c5887b186deb8679.rlib" "C:\\projects\\os-info\\target\\debug\\deps\\libkernel32-beacffc979f26c46.rlib" "C:\\projects\\os-info\\target\\debug\\deps\\libuser32-fbb28ae30109687c.rlib" "C:\\projects\\os-info\\target\\debug\\deps\\libwinapi-bb7af3f2a31ea235.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd-60d4a252bdda9250.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libpanic_unwind-0b63e20460046692.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libunwind-7daa32005d584d8a.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liblibc-49ff25caaa6e945f.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc_system-a05404e5e059417a.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\liballoc-f824a78e715239af.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libstd_unicode-2abaea46f194a6e1.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\librand-81cbf6f1d5a19206.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcore-f2bd2d524c6ace24.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\libcompiler_builtins-c6139fac5e899293.rlib" "-Wl,-Bdynamic" "-l" "ntdll" "-l" "kernel32" "-l" "user32" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-Wl,-Bstatic" "-l" "gcc_eh" "-l" "pthread" "-Wl,-Bdynamic" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\x86_64-pc-windows-gnu\\lib\\rsend.o"
  = note: ld: cannot find -lntdll

NTDLL.DLL已链接on line 12 of this file

我没有发现任何关于链接到NTDLL的问题。我找到了How do I specify the linker path in Rust?,但这个解决方案对我来说也不起作用。我在Cygwin的/usr/lib/w32api目录中找到了“libntdll.a”库,但似乎GCC没有使用它。

在针对GNU时,有没有办法让它在Windows上运行,或者在链接系统DLL时我被迫使用MSVC目标?

2 个答案:

答案 0 :(得分:1)

我通过查看winapi crate repository来了解如何做到这一点。

因为,0.2.8的crate不支持RtlGetVersion()DLL函数,所以我必须在repo中包含libntdll.a。完成后,我必须创建一个自定义构建脚本来包含库的源路径。

```

/// build.rs
/// Run custom functionality when a build executes
fn main() {
    use std::env::var;
    use std::path::Path;

    // When targeting x86_64-pc-windows-gnu, we need to include the DLL libraries
    // found in the lib/x86_64 directory
    if var("TARGET").map(|target| target == "x86_64-pc-windows-gnu").unwrap_or(false) {
        let dir = var("CARGO_MANIFEST_DIR").unwrap();
        println!("cargo:rustc-link-search=native={}", Path::new(&dir).join("lib/x86_64").display());
    }

    // When targeting i686-pc-windows-gnu, we need to include the DLL libraries
    // found in the lib/i686 directory
    if var("TARGET").map(|target| target == "i686-pc-windows-gnu").unwrap_or(false) {
        let dir = var("CARGO_MANIFEST_DIR").unwrap();
        println!("cargo:rustc-link-search=native={}", Path::new(&dir).join("lib/i686").display());
    }
}

```

答案 1 :(得分:0)

默认情况下 ntdll.dll 文件不在 GNU windows 目标的路径上,因此您可以通过在 build.rs 文件中写入以下内容来添加它:

fn main() {
    println!(r"cargo:rustc-link-search=C:\windows\system32");
}