Rust Ubuntu下编译生成环境win程序踩坑指南

前言:

1,公司要给一线搞一个升级程序,需要在win下跑。 之前都是找开发总监帮忙,但是他最近比较忙。就让我自己搞。有了下文.。说来惭愧,之前写过一篇ubuntu下编译windows的文章。里面的demo就一句话 fuck world。依赖的库很少。这个是公司的工程,依赖的库很多。想的有点简单了。大家还是要把底子打好

工程介绍。

需要编译patch.rs这个文件。

1,安装target

bash 复制代码
rustup target add x86_64-pc-windows-gnu

2,安装gcc

bash 复制代码
  sudo apt-get install mingw-w64

执行编译后提示

第一个坑:

bash 复制代码
warning: [email protected]: c/windows.c:4:10: fatal error: windows.h: No such file or directory
warning: [email protected]:     4 | #include <windows.h>
warning: [email protected]:       |          ^~~~~~~~~~~
warning: [email protected]: compilation terminated.

error: failed to run custom build command for sys-info v0.9.1

Caused by:
  process didn't exit successfully: /data/anymembak/target/debug/build/sys-info-f88ff491732c39f9/build-script-build (exit status: 1)
  --- stdout
  TARGET = Some("x86_64-pc-windows-gnu")
  OPT_LEVEL = Some("0")
  HOST = Some("x86_64-unknown-linux-gnu")
  cargo:rerun-if-env-changed=CC_x86_64-pc-windows-gnu
  CC_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=CC_x86_64_pc_windows_gnu
  CC_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_CC
  TARGET_CC = None
  cargo:rerun-if-env-changed=CC
  CC = Some("/usr/bin/gcc")
  cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT
  cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("true")
  CARGO_CFG_TARGET_FEATURE = Some("cmpxchg16b,fxsr,sse,sse2,sse3")
  cargo:rerun-if-env-changed=CFLAGS_x86_64-pc-windows-gnu
  CFLAGS_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=CFLAGS_x86_64_pc_windows_gnu
  CFLAGS_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_CFLAGS
  TARGET_CFLAGS = None
  cargo:rerun-if-env-changed=CFLAGS
  CFLAGS = None
  cargo:warning=c/windows.c:4:10: fatal error: windows.h: No such file or directory
  cargo:warning=    4 | #include <windows.h>
  cargo:warning=      |          ^~~~~~~~~~~
  cargo:warning=compilation terminated.

  --- stderr


  error occurred: Command "/usr/bin/gcc" "-O0" "-ffunction-sections" "-fdata-sections" "-gdwarf-2" "-fno-omit-frame-pointer" "-m64" "-Wall" "-Wextra" "-o" "/data/anymembak/target/x86_64-pc-windows-gnu/debug/build/sys-info-20c4b6441d409db8/out/db3b6bfb95261072-windows.o" "-c" "c/windows.c" with args gcc did not execute successfully (status code exit status: 1).


warning: build failed, waiting for other jobs to finish...
error: failed to run custom build command for openssl-sys v0.9.102

Caused by:
  process didn't exit successfully: /data/anymembak/target/debug/build/openssl-sys-e6c4b7d6399b36bc/build-script-main (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=X86_64_PC_WINDOWS_GNU_OPENSSL_NO_VENDOR
  X86_64_PC_WINDOWS_GNU_OPENSSL_NO_VENDOR unset
  cargo:rerun-if-env-changed=OPENSSL_NO_VENDOR
  OPENSSL_NO_VENDOR unset
  cargo:rerun-if-env-changed=CC_x86_64-pc-windows-gnu
  CC_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=CC_x86_64_pc_windows_gnu
  CC_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_CC
  TARGET_CC = None
  cargo:rerun-if-env-changed=CC
  CC = Some("/usr/bin/gcc")
  cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT
  cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("true")
  CARGO_CFG_TARGET_FEATURE = Some("cmpxchg16b,fxsr,sse,sse2,sse3")
  cargo:rerun-if-env-changed=CFLAGS_x86_64-pc-windows-gnu
  CFLAGS_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=CFLAGS_x86_64_pc_windows_gnu
  CFLAGS_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_CFLAGS
  TARGET_CFLAGS = None
  cargo:rerun-if-env-changed=CFLAGS
  CFLAGS = None
  cargo:rerun-if-env-changed=AR_x86_64-pc-windows-gnu
  AR_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=AR_x86_64_pc_windows_gnu
  AR_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_AR
  TARGET_AR = None
  cargo:rerun-if-env-changed=AR
  AR = None
  RUSTC_LINKER = Some("x86_64-w64-mingw32-gcc")
  cargo:rerun-if-env-changed=CROSS_COMPILE
  CROSS_COMPILE = None
  cargo:rerun-if-env-changed=ARFLAGS_x86_64-pc-windows-gnu
  ARFLAGS_x86_64-pc-windows-gnu = None
  cargo:rerun-if-env-changed=ARFLAGS_x86_64_pc_windows_gnu
  ARFLAGS_x86_64_pc_windows_gnu = None
  cargo:rerun-if-env-changed=TARGET_ARFLAGS
  TARGET_ARFLAGS = None
  cargo:rerun-if-env-changed=ARFLAGS
  RANLIBFLAGS = None
  running cd "/data/anymembak/target/x86_64-pc-windows-gnu/debug/build/openssl-sys-22d1608ab45429ff/out/openssl-build/build/src" && env -u CROSS_COMPILE AR="x86_64-w64-mingw32-ar" CC="/usr/bin/gcc" RANLIB="x86_64-w64-mingw32-ranlib" "perl" "./Configure" "--prefix=/data/anymembak/target/x86_64-pc-windows-gnu/debug/build/openssl-sys-22d1608ab45429ff/out/openssl-build/install" "--openssldir=SYS$MANAGER:[OPENSSL]" "no-dso" "no-shared" "no-ssl3" "no-tests" "no-comp" "no-zlib" "no-zlib-dynamic" "--libdir=lib" "no-md2" "no-rc5" "no-weak-ssl-ciphers" "no-camellia" "no-idea" "no-seed" "no-capieng" "mingw64" "-O2" "-ffunction-sections" "-fdata-sections" "-gdwarf-2" "-fno-omit-frame-pointer" "-m64" "-Wa,-mbig-obj"
  Configuring OpenSSL version 3.2.1 for target mingw64
  Using os-specific seed configuration
  Created configdata.pm
  Running configdata.pm
  Created Makefile.in
  Created Makefile
  Created include/openssl/configuration.h

  **********************************************************************
  ***                                                                ***
  ***   OpenSSL has been successfully configured                     ***
  ***                                                                ***
  ***   If you encounter a problem while building, please open an    ***
  ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
  ***   and include the output from the following command:           ***
  ***                                                                ***
  ***       perl configdata.pm --dump                                ***
  ***                                                                ***
  ***   (If you are new to OpenSSL, you might want to consult the    ***
  ***   'Troubleshooting' section in the INSTALL.md file first)      ***
  ***                                                                ***
  **********************************************************************
  running cd "/data/anymembak/target/x86_64-pc-windows-gnu/debug/build/openssl-sys-22d1608ab45429ff/out/openssl-build/build/src" && "make" "depend"

因为没有配置变量。简单的说就是用了linux下的gcc ,肯定会失败的。没有找到对应的文件。

本质是 build-script 里调用的 C/汇编工具链仍然是 Linux 的 /usr/bin/gcc / /usr/bin/as,而不是 MinGW-w64 的交叉编译器。于是:

rust 的配置文件中。增加env选项。

3,修改配置

.cargo/config.toml

bash 复制代码
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
ar     = "x86_64-w64-mingw32-ar"

rustflags = [
  "-L/usr/x86_64-w64-mingw32/lib",
  "-luser32",
  "-lgdi32",
  "-lkernel32",
  "-ladvapi32",
]


[env]
CC_x86_64_pc_windows_gnu  = "x86_64-w64-mingw32-gcc"
CXX_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-g++"
AR_x86_64_pc_windows_gnu  = "x86_64-w64-mingw32-ar"
RANLIB_x86_64_pc_windows_gnu = "x86_64-w64-mingw32-ranlib"
CFLAGS_x86_64_pc_windows_gnu = "-DWINVER=0x0600 -D_WIN32_WINNT=0x0600"
CXXFLAGS_x86_64_pc_windows_gnu = "-DWINVER=0x0600 -D_WIN32_WINNT=0x0600"

4、在执行

bash 复制代码
 note: /usr/bin/x86_64-w64-mingw32-ld: cannot find -lUser32: No such file or directory
          collect2: error: ld returned 1 exit status

ls /usr/x86_64-w64-mingw32/lib/libuser32.a 查看了下有文件。那就是没有建立链接。需要执行link命令

bash 复制代码
sudo ln -s /usr/x86_64-w64-mingw32/lib/libuser32.a \
          /usr/x86_64-w64-mingw32/lib/libUser32.a

原因:

  • x86_64-pc-windows-gnu 目标下,Rust 会让 MinGW-w64 链接器把 Windows 系统库 User32、Kernel32、Gdi32 ... 加到命令行(见源码里 -luser32 -lkernel32 等)​GitHub

  • 这些库不是 DLL,而是 导入库libuser32.alibkernel32.a ...)。它们随 MinGW-w64 CRT/headers 包一起提供。

  • 你的 Linux 系统上只装了 x86_64-w64-mingw32-gcc,却 没有装对应的 CRT 和 Win32 API 导入库 ,结果链接阶段就找不到 libuser32.a,于是报错。

吐槽:不是哥们(linux大佬们),你们这样搞 真的好吗。。。

执行。成功。朋友们 ,欢呼吧 enjoy rust 。

但是体积非常大190M。原因:

默认的 cargo buildDebug 构建,再加上:

  • Windows GNU 目标会把 libstd、OpenSSL、Paho-MQTT 等一大堆依赖全都 静态地 链进去;

  • Debug 模式保留完整符号表,方便 gdb/VS Code 调试;

  • 没有做 LTO/代码裁剪;

所以可执行文件非常大(上百 MB 很正常)。

执行优化命令

bash 复制代码
cargo build -p ${crate}--example patch --release --target x86_64-pc-windows-gnu
  • -p/--package test告诉 Cargo 只对 test这个包动手,避免工作区里其它 crate 被顺带编译。

  • --example patch 表示只编译 examples/patch.rs 生成的可执行文件。

体积:27M

继续优化

bash 复制代码
cargo build -p {$crate}--example patch --profile release-size  --target x86_64-pc-windows-gnu

体积:1.6M 。完美。

解析:release-size

cargo.toml中添加 ;减少其他的附带项

复制代码
[profile.release-size]
inherits = "release"
# https://www.aloxaf.com/2018/09/reduce_rust_size/
strip = true  # Automatically strip symbols from the binary.
opt-level = 'z'  # Optimize for size.
lto = true #
panic = 'abort'
codegen-units = 1

GAME OVER

====这不是最后的

bash 复制代码
error: linking with x86_64-w64-mingw32-gcc failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/bruce/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/opt/apps/com.volcengine.feilian/files/mdm/opt/corplink-mdm/bin:/usr/arm-linux-gnueabihf/bin:/opt/arm-linux-musleabihf-cross/bin:/usr/bin:/usr/arm-linux-gnueabihf/bin:/opt/arm-linux-musleabihf-cross/bin:/usr/bin:/usr/arm-linux-gnueabihf/bin:/opt/arm-linux-musleabihf-cross/bin:/usr/bin" VSLANG="1033" "x86_64-w64-mingw32-gcc" "-fno-use-linker-plugin" "-Wl,--dynamicbase" "-Wl,--disable-auto-image-base" "-m64" "-Wl,--high-entropy-va" "/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/rsbegin.o" "/tmp/rustcXg6Ks4/symbols.o" "/data/a/target/x86_64-pc-windows-gnu/release-size/deps/apm-9332c89c545fc484.apm.49192088e6a58101-cgu.0.rcgu.o" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/deps" "-L" "/data/a/target/release-size/deps" "-L" "/home/bruce/.cargo/registry/src/172.16.125.28-0c009ce4dc666fcd/windows_x86_64_gnu-0.48.5/lib" "-L" "/home/bruce/.cargo/registry/src/172.16.125.28-0c009ce4dc666fcd/windows_x86_64_gnu-0.52.5/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/openssl-sys-fc0e3cf9791f0c87/out/openssl-build/install/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/libz-ng-sys-4496acf21f6c5d86/out/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/libz-ng-sys-4496acf21f6c5d86/out/lib64" "-L" "/home/bruce/.cargo/registry/src/172.16.125.28-0c009ce4dc666fcd/winapi-x86_64-pc-windows-gnu-0.4.0/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/rdkafka-sys-c542daaeb01821a5/out/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/libz-sys-2a5b747d96b409af/out/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/libz-sys-2a5b747d96b409af/out/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/ring-b136e78e66c2fc5d/out" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/bzip2-sys-deae5791ed63b43a/out/lib" "-L" "/data/a/target/x86_64-pc-windows-gnu/release-size/build/zstd-sys-b793f55346992187/out" "-L" "/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib" "-Wl,-Bstatic" "/tmp/rustcXg6Ks4/libzstd_sys-599e1ba35eab961b.rlib" "/tmp/rustcXg6Ks4/libbzip2_sys-ef97b0b83aecce6e.rlib" "/tmp/rustcXg6Ks4/librdkafka_sys-b6c359dfa7f2ba04.rlib" "/tmp/rustcXg6Ks4/liblibz_sys-cdbcc05b320ff190.rlib" "/tmp/rustcXg6Ks4/libopenssl_sys-03b3492ba7b502cd.rlib" "/tmp/rustcXg6Ks4/libring-c9a050c1e55b0ed1.rlib" "/tmp/rustcXg6Ks4/liblibz_ng_sys-0100ee76e53efe33.rlib" "/tmp/rustcXg6Ks4/libstd-a1f74822451877d1.rlib" "/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/libcompiler_builtins-b44a9797859024b2.rlib" "-Wl,-Bdynamic" "-liphlpapi" "-lPacket" "-lgdi32" "-luser32" "-lcrypt32" "-lws2_32" "-ladvapi32" "-lwinapi_advapi32" "-lwinapi_cfgmgr32" "-lwinapi_comctl32" "-lwinapi_gdi32" "-lwinapi_kernel32" "-lwinapi_msimg32" "-lwinapi_opengl32" "-lwinapi_setupapi" "-lwinapi_user32" "-lwinapi_winspool" "-lwinapi_ws2_32" "-lkernel32" "-lwindows.0.52.0" "-lbcrypt" "-ladvapi32" "-lwindows.0.52.0" "-lntdll" "-lwindows.0.48.5" "-lwindows.0.52.0" "-lkernel32" "-ladvapi32" "-lkernel32" "-lntdll" "-luserenv" "-lws2_32" "-lkernel32" "-lws2_32" "-lkernel32" "-lgcc_eh" "-l:libpthread.a" "-lmsvcrt" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-luser32" "-lkernel32" "-Wl,--nxcompat" "-L" "/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib" "-o" "/data/a/target/x86_64-pc-windows-gnu/release-size/deps/apm-9332c89c545fc484.exe" "-Wl,--gc-sections" "-no-pie" "-Wl,--strip-all" "-nodefaultlibs" "-Wl,--disable-runtime-pseudo-reloc" "/home/bruce/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/rsend.o"
  = note: /usr/bin/x86_64-w64-mingw32-ld: cannot find -lPacket: No such file or directory
          collect2: error: ld returned 1 exit status

之后我编译了整个crate,提示上面的问题。

cargo tree -e features | grep -i packet

能快速定位是哪条依赖链、哪个 feature 打开的,方便你决定 "装 SDK" 还是 "关 feature

-lPacket 指的是 WinPcap / Npcap SDK 里的 Packet.lib (或 libPacket.a)

在 Windows 下,只要你链接了 librdkafka、pnet、winpcap 等底层网络库,build-rs 通常都会

没有lib文件

  1. 下载 Npcap SDK

    https://npcap.com/#downloadNpcap SDK(ZIP)。

  2. 拷贝头文件与静态库 (假设 SDK 解压到 ~/npcap-sdk):

    bash 复制代码
    sudo cp -R ~/npcap-sdk/Include/*  /usr/x86_64-w64-mingw32/include/
    sudo cp ~/npcap-sdk/Lib/x64/Packet.lib  /usr/x86_64-w64-mingw32/lib/
复制代码
在编译。成功。结束
相关推荐
林九生42 分钟前
【运维】Ubuntu apt 更新失败?Temporary failure resolving ‘cn.archive.ubuntu.com‘ 问题
运维·ubuntu·postgresql
夕水1 小时前
自动化按需导入组件库的工具rust版本完成开源了
前端·rust·trae
davenian2 小时前
< 自用文 rclone > 在 Ubuntu 24 访问 Google Drive 网络内容
linux·ubuntu·rclone
s9123601013 小时前
Rust std::thread::spawn(move) 的作用
开发语言·后端·rust
智想天开3 小时前
14.外观模式:思考与解读
windows·microsoft·设计模式·外观模式
悟能不能悟3 小时前
windows如何使用cmd命令翻转屏幕
windows
晚上不睡觉的周某人4 小时前
Java应用7(类集)
java·开发语言·windows
海天鹰5 小时前
Catsxp:STATUS_BREAKPOINT
windows
刘大猫.5 小时前
Centos Ubuntu RedOS系统类型下查看系统信息
linux·ubuntu·centos·ip·ifconfig·redos·查询系统信息