How to build both 32- and 64-bit app on Windows

#1

I want to build both 32- and 64-bit binaries of an application on Windows 7-64. I have installed the stable-i686 and stable-x86_64 toolchains and have built the application as 64-bit with no problems. But the 32-bit one ends up with some 64-bit code and won’t run.

I use two .bat files to build:

rustup default stable-i686-pc-windows-msvc
SET CARGO_TARGET_DIR=C:\tmp\targets\myapp32
SET RELEASE_DIR=%CARGO_TARGET_DIR%\release
mkdir %RELEASE_DIR%
cargo build --release
copy %RELEASE_DIR%\myapp.exe ..\files32

and

rustup default stable-x86_64-pc-windows-msvc
SET CARGO_TARGET_DIR=C:\tmp\targets\myapp64
SET RELEASE_DIR=%CARGO_TARGET_DIR%\release
mkdir %RELEASE_DIR%
cargo build --release
copy %RELEASE_DIR%\myapp.exe ..\files64

Is there something I’m missing or doing wrong — or is there a better approach?

0 Likes

#2

I’ve now tried using a different approach:

SET CARGO_TARGET_DIR=C:\tmp\targets\myapp64
SET RELEASE_DIR=%CARGO_TARGET_DIR%\release
mkdir %RELEASE_DIR%
cargo build --target=x86_64-pc-windows-msvc --release
copy %RELEASE_DIR%\myapp.exe ..\files64

This works fine (as the previous version did).
But building for 32-bits doesn’t work.
I believe I have the correct toolchains installed:

C:\>rustup toolchain list
stable-i686-pc-windows-msvc
stable-x86_64-pc-windows-msvc (default)

But when I try:

SET CARGO_TARGET_DIR=C:\tmp\targets\myapp32
SET RELEASE_DIR=%CARGO_TARGET_DIR%\release
mkdir %RELEASE_DIR%
cargo build --target=i686-pc-windows-msvc --release
copy %RELEASE_DIR%\myapp.exe ..\files32

It won’t build. (I know the copy won’t work either, but I don’t get that far.)
It reports:

V:\myapp>cargo build --target=i686-pc-windows-msvc --release
   Compiling rand_core v0.4.0
   Compiling unicode-width v0.1.5
   Compiling lazy_static v1.3.0
   Compiling ucd-util v0.1.3
error[E0463]: can't find crate for `core`
error[E0463]: can't find crate for `core`
  |
  |
  = note: the `i686-pc-windows-msvc` target may not be installed

So I’m stuck!

0 Likes

#3

What you want is rustup target add i686-pc-windows-msvc.

0 Likes

#4

Thank you. That gets me further.

Now my 64-bit .bat file is:

SET ARCH=x86_64-pc-windows-msvc
SET CARGO_TARGET_DIR=C:\tmp\targets\myapp64
SET RELEASE_DIR=%CARGO_TARGET_DIR%\%ARCH%\release
cargo build --target=%ARCH% --release
copy %RELEASE_DIR%\myapp.exe c:\bin\myapp64.exe

with the 32-bit only different by having the different ARCH and target dir & exe name.

However, although the 32-bit exe now builds, it crashes when run due to a “BEX” error even after I did a cargo clean and rebuilt it.

The depends program reports a problem with the 32-bit exe: “Error: Modules with different CPU types were found.” Which sounds to me like I have some 64-bit artifacts even though I build the 32- and 64-bit versions in different target dirs.

0 Likes

#5

Are you using any C dependencies? Maybe the sys crates find 64-bit libraries.

0 Likes

#6

I’m not aware that I have any C dependencies: the app is pure rust + some access to DLLs (for which I have a cfg to choose 32- or 64 bits). But I use lots of crates so maybe one of those is 64 bit only. I’ll try again with a small example app.

0 Likes

#7

BTW, cargo tree can show you all the deps.

0 Likes

#8

I had a look through Cargo.lock and there are lots of -sys crates I’m using.

I also tried building a really tiny example both 32- and 64-bit and both built and ran fine.
And I also tried building my qtrac-retest crate both 32- and 64-bit, and again both built and ran fine.

So for the larger app I’m working on I think you’re right that I have a crate dependency that’s 64-bit only. But even if I found out which one (or ones) it is, knowing that won’t give me a 32-bit build.

I thought that crates.io did some automated build tests? Maybe it could say which triples (of those tested) work and which don’t?

0 Likes

#9

Knowing which dependency it is could help you file a bug and get it fixed. Sys crates usually also have a way to force them to build a static library from source instead of searching the system for it.

crates.io doesn’t build packages. Indirectly docs.rs and “crater runs” do it, but not on Windows, and not cross-compiled.

Try building with --verbose flag. Maybe you’ll notice wrong library paths.

0 Likes

#10

Unfortunately, I’ve now removed all the 32-bit support. It was only a “nice to have” for me and had the disadvantage of doubling the number of packages and tests. I know that people use virtual machines, but I don’t really know why people still use 32 bits (although I do have two ancient laptops that are 32 bits, so maybe other people hang on to old machines too).

0 Likes

#11

I finally built my application on a Win7-32 bit system. So now I suspect that the winapi module was maybe using kernel-sys when I build in both 32- and 64-bit mode on Win7-64, but correctly uses kernel32-sys on Win7-32. (I can’t be certain though because I now only have a 64-bit toolchain on the 64-bit system and a 32-bit toolchain on the 32-bit system).

0 Likes