Setting a Rust Executable's Icon in Windows

January 5, 2021Mason Remaleyway-of-rheagamesgamedevtechrust

This morning, I decided it was long overdue that Way of Rhea get its own icon.

way of rhea icon

I believe that if you’re building a project in Visual Studio there’s a UI through which you can change your exe’s icon–but I’m not a Visual Studio user. It took me quite a while to figure out how to set an exe’s icon from the command line, so I figured I’d document what I learned here in the hopes of saving someone else some time.

It’s possible to dynamically load and set a window icon via code, but for the icon to show up in the file explorer it actually needs to be baked into the executable. This makes sense–explorer.exe shouldn’t have to have to run an executable to determine its icon!

The rest of this post will walk you through how to do this. The only Rust specific bit is the syntax by which I pass arguments to the linker.

1. Create an icon

First, you’ll need to create a square image ideally at least 256x256px, and save it as a .ico. If you’re not sure how to create a .ico, you can use GIMP or ImageMagick.

2. Create a resources file

Next, you’ll need to create a .rc file that provides the icon path. Here’s what it should look like assuming you aren’t including any other resources:

resources.rc

arbitrary_name_here ICON "path\to\your\icon.ico"

3. Compile the resources file

Next, you’ll need to compile your .rc file. The official way to do this is via rc.exe.

Unfortunately, rc.exe is not in the path by default, so you’ll need to find it. Mine is located at C:\Program Files\ (x86)\Windows Kits\10\bin\10.0.18362.0\x86\rc.exe. It was likely placed there when I installed Visual Studio.

Once you’ve located rc.exe, you can use it to compile your .rc file into a .res file:

rc resources.rc

Programmatically determining the path to rc.exe is, unfortunately, not easy. If you need to do this, here are some options:

If you’ve found a better way to do this, or know if it’s possible to use vswhere for this purpose, let me know and I’ll update this post!

Quick update: Window icons

Window icons and executable icons are set separately.

If you’d like to set a window icon to be equivalent to your executable icon, load the icon with LoadIconA and the arbitrary name you specified in your resources file. Once it’s loaded, store the result in hIcon and hIconSm on your window class.

HICON icon = LoadIconA(hInstance, "arbitrary_name_here");
global_window_class.hIcon = icon;
global_window_class.hIconSm = icon;

LoadIconA is defined in winuser.h (included in Windows.h) and requires linking with User32.lib.

If the icon doesn’t exist, LoadIconA will return NULL and a GetLastError flag will be set.