लिनक्स से विंडोज के निष्पादन के लिए क्रॉस संकलन रस्ट

संभवत: यह बहुत आश्चर्यचकित करने वाला होगा कि अगर मैं यहां हैबर आईटी साइट पर हूं, तो मैं कहूंगा कि मैं कभी-कभी खुद को प्रोग्रामिंग के लिए लाड़ करता हूं।


मेरा मुख्य ओएस लिनक्स है, लेकिन कभी-कभी मुझे विंडोज के लिए निष्पादन योग्य फाइलें भी एकत्र करनी पड़ती हैं। और हां, मैं वास्तव में केवल विधानसभा के लिए विंडोज में रिबूट नहीं करना चाहता। सी और सी ++ भाषाओं के साथ कोई समस्या नहीं है, लंबे समय से एक क्रॉस-कंपाइलर है MinGWजो यह बहुत अच्छी तरह से करता है। शुरू में उनके बारे में Pythonऔर Javaयहां तक ​​कि उल्लेख के लायक नहीं, क्रॉस-प्लेटफॉर्म। लेकिन पिछले साल मैंने रूस्ट के रूप में इस तरह की एक नई भाषा का प्रयास करने का फैसला किया। जंग वितरण किट में शामिल पैकेज मैनेजर का उपयोग करके निष्पादन योग्य फ़ाइल को इकट्ठा करते समय, यह cargoएक कुंजी निर्दिष्ट करने के लिए पर्याप्त लगता है --targetजिसके साथ परिणामी प्रोसेसर, आर्किटेक्चर और एबीआई निर्दिष्ट करें और, लिनक्स से निर्माण करते समय, exe प्राप्त करें, जो विंडोज के लिए मानक फ़ाइल होगी। लेकिन ऐसा करने की कोशिश कर रहा है:


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`.

अगर किसी को इसमें दिलचस्पी है कि मैंने इसे कैसे पार किया और अब मैं आसानी से लिनक्स के बिना विंडोज के लिए जंग कार्यक्रमों को पार कर सकता हूं, तो बिल्ली का स्वागत करें।


अस्वीकरण

32bit 64bit pc-windows-gnu, pc-windows-msvc . Linux, , Fedora Linux 31, Linux . Rust The Rust toolchain installer, Fedora Rust , nightly Rust, , , .


सबसे पहले, हम यह सुनिश्चित करते हैं कि हमने निम्नलिखित कमांड चलाकर आवश्यक लक्ष्य निर्धारित किए हैं:


rustup target list

हमें सभी संभावित लक्ष्यों की एक सूची मिलती है, और हमारे द्वारा निर्धारित लक्ष्य:


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)
[...]

लिनक्स से विंडोज के लिए निष्पादन योग्य फाइलें बनाने के लिए, हमें i686-pc-windows-gnu32bit exe और x86_64-pc-windows-gnu64bit exe के लिए लक्ष्य चाहिए यदि इन लक्ष्यों को चिह्नित नहीं किया जाता है (installed), तो हम उन्हें कमांड का उपयोग करके वितरित करते हैं


rustup target add _

यह सुनिश्चित करने के बाद कि हमारे पास एक क्रॉस कंपाइलर है जिसे MinGWचलाने से स्थापित किया गया है


rpm -qa | grep mingw

या हमारे लिनक्स वितरण के लिए एक और पैकेज मैनेजर:


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

यदि नहीं, तो MinGWचलाकर आवश्यक पैकेज स्थापित करें


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.


मैं विवरण में नहीं जा सकता कि कैसे फिर से इकट्ठा करना है MinGW, यह इतना मुश्किल नहीं है और इतना दिलचस्प नहीं है ( configureआपको इसे एक पैरामीटर के साथ चलाने की आवश्यकता है --disable-sjlj-exceptions, बाकी तुच्छ है), मैं केवल एक ही बात कहूंगा: MinGWस्टैक बाइंडिंग के साथ पुनर्निर्माण के बाद , Dwarfइसके बजाय SJLJआपको केवल एक फ़ाइल नामक एक फ़ाइल लेने की आवश्यकता है libgcc_eh.aऔर उद्देश्य के लिए इसे लाइब्रेरी डायरेक्टरी में रखा i686-pc-windows-gnuउसके बाद, जिन परियोजनाओं में पैनिक फ़ंक्शंस का उपयोग किया जाता है, उन्हें न केवल 64 बिट विंडोज उद्देश्यों के लिए एकत्र किया जाएगा, बल्कि 32 बिट के लिए भी:


[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]$ 

इस तरह किसी तरह।


All Articles