Skip to content

Commit 4268e7e

Browse files
committed
Auto merge of #60260 - videolabs:rust_uwp2, r=alexcrichton
Add support for UWP targets Hi, This pull request aims at adding support for UWP (Universal Windows Apps) platform. A few notes: - This requires a very recent mingw-w64 version (containing this commit and the previous related ones: mirror/mingw-w64@e8c433c#diff-eefdfbfe9cec5f4ebab88c9a64d423a9) - This was tested using LLVM/clang rather than gcc, and so far it assumes that LLVM/clang will be the native compiler. This is mostly due to the fact that the support for exceptions/stack unwinding for UWP got much more attention in libunwind - The "uwp" part of the target needs support for it in the `cc-rs` & `backtrace-rs` crates. I'll create the MR there right after I submit this one and will link everything together, but I'm not sure what's the correct way of dealing with external dependencies in the context of rust - Enabling import libraries and copying them across stages requires a change in cargo, for which I'll open a MR right after I submit this one as well - The i686 stack unwinding is unsupported for now, because LLVM assumes SjLj, while rust seems to assume SEH will be used. I'm unsure how to fix this Also, this is my first encounter with rust, so please bear with my code, it might not feel so idiomatic or even correct :) I'm pretty sure there's a way of doing things in a cleaner way when it comes to win/c.rs, maybe having a UWP & desktop specific modules, and import those conditionally? It doesn't feel right to sprinkle `#[cfg(...)]` all over the place Off course, I'll gladly update anything you see fit (to the extent of my abilities/knowledge :) )! Thanks,
2 parents 1863067 + 7ed5c36 commit 4268e7e

File tree

20 files changed

+529
-117
lines changed

20 files changed

+529
-117
lines changed

src/bootstrap/compile.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl Step for StartupObjects {
325325
fn run(self, builder: &Builder<'_>) {
326326
let for_compiler = self.compiler;
327327
let target = self.target;
328-
if !target.contains("pc-windows-gnu") {
328+
if !target.contains("windows-gnu") {
329329
return
330330
}
331331

@@ -1126,6 +1126,7 @@ pub fn run_cargo(builder: &Builder<'_>,
11261126
// Skip files like executables
11271127
if !filename.ends_with(".rlib") &&
11281128
!filename.ends_with(".lib") &&
1129+
!filename.ends_with(".a") &&
11291130
!is_dylib(&filename) &&
11301131
!(is_check && filename.ends_with(".rmeta")) {
11311132
continue;

src/librustc_codegen_ssa/back/linker.rs

+20
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,26 @@ impl<'a> Linker for GccLinker<'a> {
368368
}
369369
} else {
370370
self.cmd.arg("-shared");
371+
if self.sess.target.target.options.is_like_windows {
372+
// The output filename already contains `dll_suffix` so
373+
// the resulting import library will have a name in the
374+
// form of libfoo.dll.a
375+
let implib_name = out_filename
376+
.file_name()
377+
.and_then(|file| file.to_str())
378+
.map(|file| format!("{}{}{}",
379+
self.sess.target.target.options.staticlib_prefix,
380+
file,
381+
self.sess.target.target.options.staticlib_suffix));
382+
if let Some(implib_name) = implib_name {
383+
let implib = out_filename
384+
.parent()
385+
.map(|dir| dir.join(&implib_name));
386+
if let Some(implib) = implib {
387+
self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
388+
}
389+
}
390+
}
371391
}
372392
}
373393

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use crate::spec::{LinkerFlavor, Target, TargetResult};
2+
3+
pub fn target() -> TargetResult {
4+
let mut base = super::windows_uwp_base::opts();
5+
base.cpu = "pentium4".to_string();
6+
base.max_atomic_width = Some(64);
7+
base.eliminate_frame_pointer = false; // Required for backtraces
8+
9+
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
10+
// space available to x86 Windows binaries on x86_64.
11+
base.pre_link_args
12+
.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--large-address-aware".to_string());
13+
14+
Ok(Target {
15+
llvm_target: "i686-pc-windows-gnu".to_string(),
16+
target_endian: "little".to_string(),
17+
target_pointer_width: "32".to_string(),
18+
target_c_int_width: "32".to_string(),
19+
data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(),
20+
arch: "x86".to_string(),
21+
target_os: "windows".to_string(),
22+
target_env: "gnu".to_string(),
23+
target_vendor: "uwp".to_string(),
24+
linker_flavor: LinkerFlavor::Gcc,
25+
options: base,
26+
})
27+
}

src/librustc_target/spec/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ mod solaris_base;
6060
mod uefi_base;
6161
mod windows_base;
6262
mod windows_msvc_base;
63+
mod windows_uwp_base;
6364
mod thumb_base;
6465
mod l4re_base;
6566
mod fuchsia_base;
@@ -434,6 +435,8 @@ supported_targets! {
434435

435436
("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
436437
("i686-pc-windows-gnu", i686_pc_windows_gnu),
438+
("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
439+
("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
437440

438441
("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
439442
("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
2+
use std::default::Default;
3+
4+
pub fn opts() -> TargetOptions {
5+
let mut pre_link_args = LinkArgs::new();
6+
pre_link_args.insert(LinkerFlavor::Gcc, vec![
7+
// Tell GCC to avoid linker plugins, because we are not bundling
8+
// them with Windows installer, and Rust does its own LTO anyways.
9+
"-fno-use-linker-plugin".to_string(),
10+
11+
// Always enable DEP (NX bit) when it is available
12+
"-Wl,--nxcompat".to_string(),
13+
]);
14+
15+
let mut late_link_args = LinkArgs::new();
16+
late_link_args.insert(LinkerFlavor::Gcc, vec![
17+
//"-lwinstorecompat".to_string(),
18+
//"-lmingwex".to_string(),
19+
//"-lwinstorecompat".to_string(),
20+
"-lwinstorecompat".to_string(),
21+
"-lruntimeobject".to_string(),
22+
"-lsynchronization".to_string(),
23+
"-lvcruntime140_app".to_string(),
24+
"-lucrt".to_string(),
25+
"-lwindowsapp".to_string(),
26+
"-lmingwex".to_string(),
27+
"-lmingw32".to_string(),
28+
]);
29+
30+
TargetOptions {
31+
// FIXME(#13846) this should be enabled for windows
32+
function_sections: false,
33+
linker: Some("gcc".to_string()),
34+
dynamic_linking: true,
35+
executables: false,
36+
dll_prefix: String::new(),
37+
dll_suffix: ".dll".to_string(),
38+
exe_suffix: ".exe".to_string(),
39+
staticlib_prefix: "lib".to_string(),
40+
staticlib_suffix: ".a".to_string(),
41+
no_default_libraries: true,
42+
target_family: Some("windows".to_string()),
43+
is_like_windows: true,
44+
allows_weak_linkage: false,
45+
pre_link_args,
46+
pre_link_objects_exe: vec![
47+
"rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
48+
],
49+
pre_link_objects_dll: vec![
50+
"rsbegin.o".to_string(),
51+
],
52+
late_link_args,
53+
post_link_objects: vec![
54+
"rsend.o".to_string(),
55+
],
56+
custom_unwind_resume: true,
57+
abi_return_struct_as_int: true,
58+
emit_debug_gdb_scripts: false,
59+
requires_uwtable: true,
60+
limit_rdylib_exports: false,
61+
62+
.. Default::default()
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use crate::spec::{LinkerFlavor, Target, TargetResult};
2+
3+
pub fn target() -> TargetResult {
4+
let mut base = super::windows_uwp_base::opts();
5+
base.cpu = "x86-64".to_string();
6+
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
7+
base.max_atomic_width = Some(64);
8+
9+
Ok(Target {
10+
llvm_target: "x86_64-pc-windows-gnu".to_string(),
11+
target_endian: "little".to_string(),
12+
target_pointer_width: "64".to_string(),
13+
target_c_int_width: "32".to_string(),
14+
data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(),
15+
arch: "x86_64".to_string(),
16+
target_os: "windows".to_string(),
17+
target_env: "gnu".to_string(),
18+
target_vendor: "uwp".to_string(),
19+
linker_flavor: LinkerFlavor::Gcc,
20+
options: base,
21+
})
22+
}

src/libstd/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ fn main() {
3939
println!("cargo:rustc-link-lib=framework=Security");
4040
println!("cargo:rustc-link-lib=framework=Foundation");
4141
println!("cargo:rustc-link-lib=resolv");
42+
} else if target.contains("uwp") {
43+
println!("cargo:rustc-link-lib=ws2_32");
44+
// For BCryptGenRandom
45+
println!("cargo:rustc-link-lib=bcrypt");
4246
} else if target.contains("windows") {
4347
println!("cargo:rustc-link-lib=advapi32");
4448
println!("cargo:rustc-link-lib=ws2_32");

0 commit comments

Comments
 (0)