Problem While Linking UEFI App


#1

I’m trying to create a UEFI application using Rust and running into a linking error as shown below:

note: "link.exe" "/NOLOGO" "/NXCOMPAT" "/SUBSYSTEM:EFI_APPLICATION" "/LIBPATH:C:\\Users\\<omitted>\\.xargo\\lib\\rustlib\\x86_64-pc-efi\\lib" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.236iz806sghm3wx.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.3jhb58qstq85dbxi.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.3ldk0i2zxftngav8.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.42vtsprd4kfze6qg.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.49a7n47po4ttqjl7.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.4yh8x2b62dcih00t.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.4ypvbwho0bu5tnww.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.98g0d9x8aw3akpe.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.9elsx31vb4it187.rcgu.o" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.aupkk7eagb5ckad.rcgu.o" "/OUT:D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.dll" "/DEF:C:\\Users\\OMIT~1.SIN\\AppData\\Local\\Temp\\rustc.4W5bK9wkbT1v\\lib.def" "D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.crate.metadata.rcgu.o" "/OPT:REF,NOICF" "/DEBUG" "/LIBPATH:D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps" "/LIBPATH:D:\\Projects\\Rust\\Boot2Rust\\target\\debug\\deps" "/LIBPATH:C:\\Users\\<omitted>\\.xargo\\lib\\rustlib\\x86_64-pc-efi\\lib" "C:\\Users\\OMIT~1.SIN\\AppData\\Local\\Temp\\rustc.4W5bK9wkbT1v\\libcore-f984d1e4f83e777d.rlib" "/DLL" "/IMPLIB:D:\\Projects\\Rust\\Boot2Rust\\target\\x86_64-pc-efi\\debug\\deps\\boot.dll.lib" = note: LINK : fatal error LNK1294: exports and import libraries are not supported with /SUBSYSTEM:EFI_APPLICATION

As the last line says, it’s basically not happy with the /IMPLIB argument being passed while I’m also passing /SUBSYSTEM:EFI_APPLICATION. I of course need the latter for building a UEFI app. So my question is, is there a way for me to prevent the /IMPLIB argument from being passed to to link.exe?

The host I’m building on is Windows and I’m using xargo with a custom target spec shown below:

 {                                                            
  "arch": "x86_64",                                          
  "cpu": "x86-64",                                           
  "crt-static-allows-dylibs": true,                          
  "crt-static-respected": true,                              
  "data-layout": "e-m:w-i64:64-f80:128-n8:16:32:64-S128",    
  "dll-prefix": "",                                          
  "dll-suffix": ".dll",                                      
  "dynamic-linking": true,                                   
  "env": "msvc",                                             
  "exe-suffix": ".exe",                                      
  "executables": true,                                       
  "has-elf-tls": true,                                       
  "is-builtin": true,                                        
  "is-like-msvc": true,                                      
  "is-like-windows": true,                                   
  "linker": "link.exe",                                      
  "linker-flavor": "msvc",                                   
  "llvm-target": "x86_64-pc-windows-msvc",                   
  "max-atomic-width": 64,                                    
  "os": "windows",                                           
  "pre-link-args": {                                         
    "msvc": [                                                
      "/NOLOGO",                                             
      "/NXCOMPAT",
      "/SUBSYSTEM:EFI_APPLICATION"                                            
    ]                                                        
  },                                                         
  "staticlib-prefix": "",                                    
  "staticlib-suffix": ".lib",                                
  "target-c-int-width": "32",                                
  "target-endian": "little",                                 
  "target-family": "windows",                                
  "target-pointer-width": "64",                              
  "vendor": "pc"                                             
}

This spec was created by copying the spec of the built-in target x86_64-pc-windows-msvc and by adding just one line which is the "/SUBSYSTEM:EFI_APPLICATION" argument.


#2

Maybe @retep998 has some ideas here so CC’ing him.

Ideally what I want is to be able to coax xargo to use the object file of my rust code in the linker invocation rather than going down the import library path. However, as I see it the use of an import library seems to be fundamental to how cargo or xargo links programs on Windows. So I’m actually myself not very sure how easy it will be to overcome this hurdle.

Will using the windows-gnu toolchain be a better alternative?


#3

Probably


#4

/IMPLIB is being passed because you’re compiling a dll so it needs that to emit an import library so other applications can link to your dll. If you’re actually trying to build an application, then perhaps you should not be asking it to create a dll? Is your project somewhere on the internet so I can try to build it myself?

Using the windows-gnu toolchain isn’t going to fix anything. It already has a hard enough time supporting mainstream Windows, so I doubt it would be any better at supporting corner cases like UEFI applications.


#5

Ah! I was assuming it’s adding /IMPLIB to consume the output of the compilation. My bad. I should have looked up the documentation of link.exe.

Anyway thanks @retep998. I guess the solution would be to change the crate type to bin. A UEFI application is in fact more akin to an EXE than a DLL anyway.