Mungkin tidak akan terlalu mengejutkan jika saya di sini di situs Habr IT, saya akan mengatakan bahwa saya kadang-kadang menikmati pemrograman.
OS utama saya adalah Linux, tetapi kadang-kadang saya juga harus mengumpulkan file yang dapat dieksekusi untuk Windows. Dan tentu saja, saya tidak ingin reboot ke Windows hanya untuk perakitan exe. Tidak ada masalah dengan bahasa C dan C ++, untuk waktu yang lama ada cross-compiler MinGW
yang melakukan ini dengan sangat baik. Tentang Python
dan Java
bahkan tidak layak disebut, lintas-platform pada awalnya. Tapi tahun lalu saya memutuskan untuk mencoba bahasa bermodel baru seperti Rust. Ketika merakit file yang dapat dieksekusi menggunakan manajer paket yang termasuk dalam kit distribusi Rust, cargo
tampaknya cukup untuk menentukan kunci --target
yang digunakan untuk menentukan prosesor, arsitektur dan ABI yang dihasilkan dan, ketika membangun dari Linux, dapatkan exe, yang akan menjadi file yang dapat dieksekusi standar untuk Windows. Tetapi mencoba melakukannya:
cargo build --target x86_64-pc-windows-gnu
Saya hanya menerima pesan kesalahan tautan:
error: linking with `gcc` failed: exit code: 1
[...]
= note: /usr/bin/ld: unrecognized option '--nxcompat'
/usr/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
Jika ada yang tertarik dengan cara saya mengatasinya dan sekarang saya dapat dengan mudah melakukan kompilasi silang program-program Rust untuk Windows tanpa meninggalkan Linux, selamat datang di cat.
Penolakan32bit 64bit pc-windows-gnu, pc-windows-msvc . Linux, , Fedora Linux 31, Linux . Rust The Rust toolchain installer, Fedora Rust , nightly Rust, , , .
Pertama-tama, kami memastikan bahwa kami telah menetapkan tujuan yang diperlukan dengan menjalankan perintah berikut:
rustup target list
Kami mendapatkan daftar semua sasaran yang mungkin, dan sasaran yang telah kami tetapkan:
aarch64-apple-ios
aarch64-fuchsia
[...]
i686-pc-windows-gnu (installed)
[...]
i686-unknown-linux-gnu (installed)
[...]
x86_64-pc-windows-gnu (installed)
x86_64-unknown-linux-gnu (installed)
[...]
Untuk membuat file yang dapat dieksekusi untuk Windows dari Linux, kita memerlukan target i686-pc-windows-gnu
untuk exe 32bit dan x86_64-pc-windows-gnu
64bit. Jika sasaran ini tidak ditandai sebagai (installed)
, maka kami mengirimkannya menggunakan perintah
rustup target add _
Setelah kami memastikan bahwa kami memiliki cross compiler yang diinstal dengan MinGW
menjalankan
rpm -qa | grep mingw
atau manajer paket lain untuk distribusi Linux kami:
mingw32-gcc-9.2.1-1.fc31.x86_64
mingw32-binutils-2.32-6.fc31.x86_64
mingw64-gcc-9.2.1-1.fc31.x86_64
mingw-binutils-generic-2.32-6.fc31.x86_64
mingw-filesystem-base-110-1.fc31.noarch
mingw64-winpthreads-6.0.0-2.fc31.noarch
mingw32-winpthreads-6.0.0-2.fc31.noarch
mingw32-crt-6.0.0-2.fc31.noarch
mingw64-binutils-2.32-6.fc31.x86_64
mingw64-crt-6.0.0-2.fc31.noarch
mingw64-filesystem-110-1.fc31.noarch
mingw32-filesystem-110-1.fc31.noarch
mingw32-cpp-9.2.1-1.fc31.x86_64
mingw64-headers-6.0.0-2.fc31.noarch
mingw32-headers-6.0.0-2.fc31.noarch
mingw64-cpp-9.2.1-1.fc31.x86_64
Jika tidak, MinGW
instal paket yang diperlukan dengan menjalankan
sudo dnf install mingw32-gcc mingw64-gcc
, (, - Test-Driven Development, :-)
Rust:
[pfemidi@pfemidi rust]$ cargo new foobar
Created binary (application) `foobar` package
[pfemidi@pfemidi rust]$ cat foobar/src/main.rs
fn main() {
println!("Hello, world!");
}
[pfemidi@pfemidi rust]$
Linux:
[pfemidi@pfemidi foobar]$ cargo run
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
Finished dev [unoptimized + debuginfo] target(s) in 1.65s
Running `target/debug/foobar`
Hello, world!
[pfemidi@pfemidi foobar]$
. x86_64-pc-windows-gnu
:
cargo build --target x86_64-pc-windows-gnu
:
error: linking with `gcc` failed: exit code: 1
[...]
= note: /usr/bin/ld: unrecognized option '--nxcompat'
/usr/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
, MinGW
, gcc
. , .cargo config :
[pfemidi@pfemidi foobar]$ mkdir .cargo
[pfemidi@pfemidi foobar]$ cat > .cargo/config
[target.i686-pc-windows-gnu]
linker = "i686-w64-mingw32-gcc"
ar = "i686-w64-mingw32-ar"
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
ar = "x86_64-w64-mingw32-ar"
[pfemidi@pfemidi foobar]$
Windows gcc
, MinGW
.
:
cargo build --target x86_64-pc-windows-gnu
, x86_64-w64-mingw32-gcc
:
error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1
[...]
= note: /usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lpthread
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
, Rust - , mingw32-winpthreads
mingw64-winpthreads
, dnf
mingw32-gcc
mingw64-gcc
mingw32-winpthreads-static
mingw64-winpthreads-static
, -lpthread
. :
sudo dnf install mingw??-winpthreads-static
:
cargo build --target x86_64-pc-windows-gnu
! :
error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1
[...]
= note: /usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o:crtexe.c:(.rdata$.refptr.__onexitbegin[.refptr.__onexitbegin]+0x0): undefined reference to `__onexitbegin'
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o:crtexe.c:(.rdata$.refptr.__onexitend[.refptr.__onexitend]+0x0): undefined reference to `__onexitend'
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
__onexitbegin
__onexitend
~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o
, x86_64-pc-windows-gnu
. , , Rust, Rust, Rust : Rust Windows, pc-windows-gnu, MinGW 6.3.0, Fedora Linux 31 MinGW 9.2.1, CRT. Ok, crt2.o MinGW Rust x86_64-pc-windows-gnu. crt2.o dllcrt2.o, :
[pfemidi@pfemidi foobar]$ cd ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/
[pfemidi@pfemidi lib]$ cp /usr/x86_64-w64-mingw32/sys-root/mingw/lib/crt2.o .
[pfemidi@pfemidi lib]$ cp /usr/x86_64-w64-mingw32/sys-root/mingw/lib/dllcrt2.o .
[pfemidi@pfemidi lib]$ cd -
/home/pfemidi/mywork/rust/foobar
[pfemidi@pfemidi foobar]$
Rust:
pfemidi@pfemidi foobar]$ cargo build --target x86_64-pc-windows-gnu
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
Finished dev [unoptimized + debuginfo] target(s) in 4.46s
[pfemidi@pfemidi foobar]$
! ! .. wine, :
[pfemidi@pfemidi foobar]$ cargo run --target x86_64-pc-windows-gnu
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
Running `target/x86_64-pc-windows-gnu/debug/foobar.exe`
Hello, world!
[pfemidi@pfemidi foobar]$
! 32bit Windows, run
build
:
error: linking with `i686-w64-mingw32-gcc` failed: exit code: 1
[...]
= note: /usr/lib/gcc/i686-w64-mingw32/9.2.1/../../../../i686-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o:crtexe.c:(.text+0x75): undefined reference to `__onexitend'
/usr/lib/gcc/i686-w64-mingw32/9.2.1/../../../../i686-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o:crtexe.c:(.text+0x7a): undefined reference to `__onexitbegin'
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
__onexitbegin
__onexitend
~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/crt2.o
, , 64bit crt2.o dllcrt2.o , MinGW
Fedora:
[pfemidi@pfemidi foobar]$ cd ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/
[pfemidi@pfemidi lib]$ cp /usr/i686-w64-mingw32/sys-root/mingw/lib/crt2.o .
[pfemidi@pfemidi lib]$ cp /usr/i686-w64-mingw32/sys-root/mingw/lib/dllcrt2.o .
[pfemidi@pfemidi lib]$ cd -
/home/pfemidi/mywork/rust/foobar
[pfemidi@pfemidi foobar]$
:
[pfemidi@pfemidi foobar]$
[pfemidi@pfemidi foobar]$ cargo run --target i686-pc-windows-gnu
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
Finished dev [unoptimized + debuginfo] target(s) in 5.12s
Running `target/i686-pc-windows-gnu/debug/foobar.exe`
Hello, world!
[pfemidi@pfemidi foobar]$
.
, (macro panic!, expect ..) 32bit Windows. 64bit , 32bit .
:
[pfemidi@pfemidi foobar]$ cat src/main.rs
fn main() {
println!("Hello, world!");
panic!("I'm panicked!"); // !
}
[pfemidi@pfemidi foobar]
64bit Windows:
[pfemidi@pfemidi foobar]$ cargo run --target x86_64-pc-windows-gnu
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
Finished dev [unoptimized + debuginfo] target(s) in 2.95s
Running `target/x86_64-pc-windows-gnu/debug/foobar.exe`
Hello, world!
thread 'main' panicked at 'I'm panicked!', src/main.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
[pfemidi@pfemidi foobar]$
, , . , 32bit Windows.
:
[pfemidi@pfemidi foobar]$ cargo run --target i686-pc-windows-gnu
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
error: linking with `i686-w64-mingw32-gcc` failed: exit code: 1
[...]
= note: /usr/lib/gcc/i686-w64-mingw32/9.2.1/../../../../i686-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libpanic_unwind-1a1fb2d4d34efaf8.rlib(panic_unwind-1a1fb2d4d34efaf8.panic_unwind.2hbcqjo8-cgu.0.rcgu.o): in function `ZN12panic_unwind3imp5panic17hdaabfe6326236dacE':
/rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8\/src\libpanic_unwind/gcc.rs:73: undefined reference to `_Unwind_RaiseException'
/usr/lib/gcc/i686-w64-mingw32/9.2.1/../../../../i686-w64-mingw32/bin/ld: /home/pfemidi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libpanic_unwind-1a1fb2d4d34efaf8.rlib(panic_unwind-1a1fb2d4d34efaf8.panic_unwind.2hbcqjo8-cgu.0.rcgu.o): in function `rust_eh_unwind_resume':
/rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8\/src\libpanic_unwind/gcc.rs:327: undefined reference to `_Unwind_Resume'
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: could not compile `foobar`.
, _Unwind_RaiseException
_Unwind_Resume
libpanic
Rust.
, , Rust, . .
Rust Dwarf
32bit Windows SEH
64bit Windows, MinGW
Fedora Linux SJLJ
32bit Windows SEH
64bit Windows ( ). 64bit , 32bit . MinGW
Dwarf
SJLJ
32bit Windows.
Saya tidak akan membahas secara terperinci tentang cara memasang kembali MinGW
, tidak begitu sulit dan tidak begitu menarik ( configure
Anda perlu menjalankannya dengan parameter --disable-sjlj-exceptions
, sisanya sepele), saya akan mengatakan satu hal: setelah MinGW
membangun kembali dengan tumpukan yang dibuka, Dwarf
alih-alih SJLJ
Anda hanya perlu mengambil satu file yang dipanggil libgcc_eh.a
dan letakkan di direktori perpustakaan untuk tujuan tersebut i686-pc-windows-gnu
. Setelah itu, proyek-proyek di mana fungsi panik digunakan akan mulai dikumpulkan tidak hanya untuk keperluan Windows 64bit, tetapi juga untuk 32bit:
[pfemidi@pfemidi foobar]$ cd ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/
[pfemidi@pfemidi lib]$ cp ~/rpmbuild/BUILD/gcc-9.2.1-20190827/build_win32/i686-w64-mingw32/libgcc/libgcc_eh.a .
[pfemidi@pfemidi lib]$ cd -
/home/pfemidi/mywork/rust/foobar
[pfemidi@pfemidi foobar]$ cargo run --target i686-pc-windows-gnu
Compiling foobar v0.1.0 (/home/pfemidi/mywork/rust/foobar)
Finished dev [unoptimized + debuginfo] target(s) in 4.57s
Running `target/i686-pc-windows-gnu/debug/foobar.exe`
Hello, world!
thread 'main' panicked at 'I'm panicked!', src/main.rs:3:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
[pfemidi@pfemidi foobar]$
Entah bagaimana caranya.