[Question] How to dllexport NvOptimusEnablement symbol to auto select dedicated Nvidia GPU?

This is a question I had asked on the rust-sdl2 repository, but it makes more sense to ask it here.
Here is the question link from there
https://github.com/AngryLawyer/rust-sdl2/issues/582

In normal C/C++ SDL2 app I wrote, adding the following code
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
causes the GPU driver system with integrated and dedicated nvidia gpu, to auto select the dedicated nvidia gpu.

I searched around rust documentation but things i found were about dllexport of pub methods of libs, not applications, and not just symbol values. I got confused about the best way to export this symbol from a normal rust app - not a lib (using crate options maybe?)

How can I make my rust app (not a library) dllexport this symbol with this value ?
I saw information about exporting public functions here
https://github.com/rust-lang/rust/issues/7196
but I could not find simple info on just exporting a value like above, and not from a library but an application.

Thanks for any links or help.

2 Likes

Did you ever found any way to do this in rust?

Yes, here is what I did.

  • Create a lib file named : NVOptimusLib.lib using the latest Visual Studio (c++) which contains the exported value.
    Use this .cpp file

#include <windows.h>

extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}

and this .def file

EXPORTS
NvOptimusEnablement DATA

  • Use this .lib file in cargo with a .cargo/config file which has the contents (the .lib file must be put at 'deps' folder. ex: target\debug\deps)
# [target.x86_64-pc-windows-msvc]
# rustflags = ["-Ctarget-feature=+crt-static"]
# [target.i686-pc-windows-msvc]
# rustflags = ["-Ctarget-feature=+crt-static"]

[target.x86_64-pc-windows-msvc]
rustflags = [ "-C", "link-args=NVOptimusLib.lib /EXPORT:NvOptimusEnablement,DATA"]  # custom flags to pass to all compiler invocations

then after cargo build I can confirm that

dumpbin /exports myapp.exe
Microsoft (R) COFF/PE Dumper Version 14.24.28315.0
Copyright (C) Microsoft Corporation. All rights reserved.

Dump of file myapp.exe

File Type: EXECUTABLE IMAGE

Section contains the following exports for myapp.exe

00000000 characteristics
FFFFFFFF time date stamp
    0.00 version
       1 ordinal base
     657 number of functions
     657 number of names

ordinal hint RVA      name

      1    0 0020D900 NvOptimusEnablement = NvOptimusEnablement

and also processexplorer tool show that the process is only using the dedicated gpu.

I now tested this with latest rust and it still works:

rustup show
Default host: x86_64-pc-windows-msvc
rustup home: C:\Users\hg\.rustup

stable-x86_64-pc-windows-msvc (default)
rustc 1.41.0 (5e1a79984 2020-01-27)

I also had to upgrade visual studio to 2019 community, since I had some linker errors with the old 2015 community version I had.

Thanks! i finally manged to do this using only rust, although it requires a nightly build since it requires an unstable feature:

#![cfg_attr(target_os="windows", feature(link_args))]

#[cfg(target_os="windows")]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static NvOptimusEnablement: std::os::raw::c_ulong = 0x00000001;

#[cfg(target_os="windows")]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static AmdPowerXpressRequestHighPerformance : std::os::raw::c_int = 1;

#[cfg(target_os="windows")]
#[link_args = "/EXPORT:NvOptimusEnablement"]
extern {}

#[cfg(target_os="windows")]
#[link_args = "/EXPORT:AmdPowerXpressRequestHighPerformance"]
extern {}

there's other ways to apply linker flags, like environment variables or flags in .cargo/config but those are applied to every dependency which makes some fail while compiling so this seems to be the only way to do it without including an external c library

I was not aware of these attributes. This is a lot cleaner than injecting to everything from cargo config.
Thanks for the update.