Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Add knowledge of Windows subsystems. #37501

Merged
merged 1 commit into from
Nov 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ fn link_natively(sess: &Session,
{
let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
link_args(&mut *linker, sess, crate_type, tmpdir,
objects, out_filename, outputs);
objects, out_filename, outputs, trans);
}
cmd.args(&sess.target.target.options.late_link_args);
for obj in &sess.target.target.options.post_link_objects {
Expand Down Expand Up @@ -711,7 +711,8 @@ fn link_args(cmd: &mut Linker,
tmpdir: &Path,
objects: &[PathBuf],
out_filename: &Path,
outputs: &OutputFilenames) {
outputs: &OutputFilenames,
trans: &CrateTranslation) {

// The default library location, we need this to find the runtime.
// The location of crates will be determined as needed.
Expand All @@ -726,6 +727,13 @@ fn link_args(cmd: &mut Linker,
}
cmd.output_filename(out_filename);

if crate_type == config::CrateTypeExecutable &&
sess.target.target.options.is_like_windows {
if let Some(ref s) = trans.windows_subsystem {
cmd.subsystem(s);
}
}

// If we're building a dynamic library then some platforms need to make sure
// that all symbols are exported correctly from the dynamic library.
if crate_type != config::CrateTypeExecutable {
Expand Down
29 changes: 29 additions & 0 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub trait Linker {
fn whole_archives(&mut self);
fn no_whole_archives(&mut self);
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
fn subsystem(&mut self, subsystem: &str);
}

pub struct GnuLinker<'a> {
Expand Down Expand Up @@ -294,6 +295,10 @@ impl<'a> Linker for GnuLinker<'a> {

self.cmd.arg(arg);
}

fn subsystem(&mut self, subsystem: &str) {
self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
}
}

pub struct MsvcLinker<'a> {
Expand Down Expand Up @@ -441,6 +446,30 @@ impl<'a> Linker for MsvcLinker<'a> {
arg.push(path);
self.cmd.arg(&arg);
}

fn subsystem(&mut self, subsystem: &str) {
// Note that previous passes of the compiler validated this subsystem,
// so we just blindly pass it to the linker.
self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem));

// Windows has two subsystems we're interested in right now, the console
// and windows subsystems. These both implicitly have different entry
// points (starting symbols). The console entry point starts with
// `mainCRTStartup` and the windows entry point starts with
// `WinMainCRTStartup`. These entry points, defined in system libraries,
// will then later probe for either `main` or `WinMain`, respectively to
// start the application.
//
// In Rust we just always generate a `main` function so we want control
// to always start there, so we force the entry point on the windows
// subsystem to be `mainCRTStartup` to get everything booted up
// correctly.
//
// For more information see RFC #1665
if subsystem == "windows" {
self.cmd.arg("/ENTRY:mainCRTStartup");
}
}
}

fn exported_symbols(scx: &SharedCrateContext,
Expand Down
17 changes: 15 additions & 2 deletions src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,7 +1611,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
metadata: metadata,
reachable: vec![],
no_builtins: no_builtins,
linker_info: linker_info
linker_info: linker_info,
windows_subsystem: None,
};
}

Expand Down Expand Up @@ -1747,14 +1748,26 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols);

let subsystem = attr::first_attr_value_str_by_name(&krate.attrs,
"windows_subsystem");
let windows_subsystem = subsystem.map(|subsystem| {
if subsystem != "windows" && subsystem != "console" {
tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \
`windows` and `console` are allowed",
subsystem));
}
subsystem.to_string()
});

CrateTranslation {
modules: modules,
metadata_module: metadata_module,
link: link_meta,
metadata: metadata,
reachable: reachable_symbols,
no_builtins: no_builtins,
linker_info: linker_info
linker_info: linker_info,
windows_subsystem: windows_subsystem,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ pub struct CrateTranslation {
pub metadata: Vec<u8>,
pub reachable: Vec<String>,
pub no_builtins: bool,
pub windows_subsystem: Option<String>,
pub linker_info: back::linker::LinkerInfo
}

Expand Down
9 changes: 9 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ declare_features! (

// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
(active, field_init_shorthand, "1.14.0", Some(37340)),

// The #![windows_subsystem] attribute
(active, windows_subsystem, "1.14.0", Some(37499)),
);

declare_features! (
Expand Down Expand Up @@ -713,6 +716,12 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
"defining reflective traits is still evolving",
cfg_fn!(reflect))),

("windows_subsystem", Whitelisted, Gated(Stability::Unstable,
"windows_subsystem",
"the windows subsystem attribute \
id currently unstable",
cfg_fn!(windows_subsystem))),

// Crate level attributes
("crate_name", CrateLevel, Ungated),
("crate_type", CrateLevel, Ungated),
Expand Down
14 changes: 14 additions & 0 deletions src/test/compile-fail/windows-subsystem-gated.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![windows_subsystem = "console"]
//~^ ERROR: the windows subsystem attribute is currently unstable

fn main() {}
15 changes: 15 additions & 0 deletions src/test/compile-fail/windows-subsystem-invalid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(windows_subsystem)]
#![windows_subsystem = "wrong"]
//~^ ERROR: invalid subsystem `wrong`, only `windows` and `console` are allowed

fn main() {}
5 changes: 5 additions & 0 deletions src/test/run-make/windows-subsystem/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-include ../tools.mk

all:
$(RUSTC) windows.rs
$(RUSTC) console.rs
15 changes: 15 additions & 0 deletions src/test/run-make/windows-subsystem/console.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(windows_subsystem)]
#![windows_subsystem = "console"]

fn main() {}

14 changes: 14 additions & 0 deletions src/test/run-make/windows-subsystem/windows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(windows_subsystem)]
#![windows_subsystem = "windows"]

fn main() {}