Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit be1d1aa

Browse files
committedMay 17, 2017
Auto merge of #41639 - ishitatsuyuki:unify-tools, r=alexcrichton
Unify tools building Close #41601 Time saving for up to 10 minutes. Cargo is now only compiled once. Downsides: - Out of tree Cargo.lock maintenance - Cargo.toml `[replace]` version maintenance
2 parents 7b5c3d2 + db69d89 commit be1d1aa

File tree

8 files changed

+1168
-209
lines changed

8 files changed

+1168
-209
lines changed
 

‎.gitmodules

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
url = https://github.com/rust-lang-nursery/nomicon.git
2424
[submodule "src/tools/cargo"]
2525
path = src/tools/cargo
26-
url = https://github.com/rust-lang/cargo
26+
url = https://github.com/rust-lang/cargo.git
2727
[submodule "reference"]
2828
path = src/doc/reference
2929
url = https://github.com/rust-lang-nursery/reference.git
@@ -32,4 +32,4 @@
3232
url = https://github.com/rust-lang/book.git
3333
[submodule "src/tools/rls"]
3434
path = src/tools/rls
35-
url = https://github.com/rust-lang-nursery/rls
35+
url = https://github.com/rust-lang-nursery/rls.git

‎src/Cargo.lock

Lines changed: 1049 additions & 72 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ members = [
1414
"tools/remote-test-client",
1515
"tools/remote-test-server",
1616
"tools/rust-installer",
17-
]
18-
19-
# These projects have their own Cargo.lock
20-
exclude = [
2117
"tools/cargo",
2218
"tools/rls",
2319
]
@@ -38,3 +34,6 @@ debug-assertions = false
3834
[profile.test]
3935
debug = false
4036
debug-assertions = false
37+
38+
[replace]
39+
"https://github.com/rust-lang/cargo#0.20.0" = { path = "tools/cargo" }

‎src/bootstrap/bin/rustc.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,24 @@ use std::path::PathBuf;
3838
use std::process::{Command, ExitStatus};
3939

4040
fn main() {
41-
let args = env::args_os().skip(1).collect::<Vec<_>>();
41+
let mut args = env::args_os().skip(1).collect::<Vec<_>>();
42+
43+
// Append metadata suffix for internal crates. See the corresponding entry
44+
// in bootstrap/lib.rs for details.
45+
if let Ok(s) = env::var("RUSTC_METADATA_SUFFIX") {
46+
for i in 1..args.len() {
47+
// Dirty code for borrowing issues
48+
let mut new = None;
49+
if let Some(current_as_str) = args[i].to_str() {
50+
if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) ||
51+
current_as_str.starts_with("-Cmetadata") {
52+
new = Some(format!("{}-{}", current_as_str, s));
53+
}
54+
}
55+
if let Some(new) = new { args[i] = new.into(); }
56+
}
57+
}
58+
4259
// Detect whether or not we're a build script depending on whether --target
4360
// is passed (a bit janky...)
4461
let target = args.windows(2)

‎src/bootstrap/bootstrap.py

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import datetime
1515
import hashlib
1616
import os
17+
import re
1718
import shutil
1819
import subprocess
1920
import sys
@@ -126,13 +127,13 @@ def unpack(tarball, dst, verbose=False, match=None):
126127
shutil.move(tp, fp)
127128
shutil.rmtree(os.path.join(dst, fname))
128129

129-
def run(args, verbose=False, exception=False):
130+
def run(args, verbose=False, exception=False, cwd=None):
130131
if verbose:
131132
print("running: " + ' '.join(args))
132133
sys.stdout.flush()
133134
# Use Popen here instead of call() as it apparently allows powershell on
134135
# Windows to not lock up waiting for input presumably.
135-
ret = subprocess.Popen(args)
136+
ret = subprocess.Popen(args, cwd=cwd)
136137
code = ret.wait()
137138
if code != 0:
138139
err = "failed to run: " + ' '.join(args)
@@ -297,8 +298,10 @@ def bin_root(self):
297298

298299
def get_toml(self, key):
299300
for line in self.config_toml.splitlines():
300-
if line.startswith(key + ' ='):
301-
return self.get_string(line)
301+
match = re.match(r'^{}\s*=(.*)$'.format(key), line)
302+
if match is not None:
303+
value = match.group(1)
304+
return self.get_string(value) or value.strip()
302305
return None
303306

304307
def get_mk(self, key):
@@ -329,6 +332,8 @@ def rustc(self):
329332

330333
def get_string(self, line):
331334
start = line.find('"')
335+
if start == -1:
336+
return None
332337
end = start + 1 + line[start + 1:].find('"')
333338
return line[start + 1:end]
334339

@@ -386,12 +391,21 @@ def build_bootstrap(self):
386391
args.append("--frozen")
387392
self.run(args, env)
388393

389-
def run(self, args, env):
390-
proc = subprocess.Popen(args, env=env)
394+
def run(self, args, env=None, cwd=None):
395+
proc = subprocess.Popen(args, env=env, cwd=cwd)
391396
ret = proc.wait()
392397
if ret != 0:
393398
sys.exit(ret)
394399

400+
def output(self, args, env=None, cwd=None):
401+
proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env, cwd=cwd)
402+
(out, err) = proc.communicate()
403+
ret = proc.wait()
404+
if ret != 0:
405+
print(out)
406+
sys.exit(ret)
407+
return out
408+
395409
def build_triple(self):
396410
default_encoding = sys.getdefaultencoding()
397411
config = self.get_toml('build')
@@ -529,6 +543,54 @@ def build_triple(self):
529543

530544
return "{}-{}".format(cputype, ostype)
531545

546+
def update_submodules(self):
547+
if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
548+
self.get_toml('submodules') == "false" or \
549+
self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1":
550+
return
551+
552+
print('Updating submodules')
553+
output = self.output(["git", "submodule", "status"], cwd=self.rust_root)
554+
submodules = []
555+
for line in output.splitlines():
556+
# NOTE `git submodule status` output looks like this:
557+
#
558+
# -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
559+
# +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
560+
# e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
561+
#
562+
# The first character can be '-', '+' or ' ' and denotes the
563+
# `State` of the submodule Right next to this character is the
564+
# SHA-1 of the submodule HEAD And after that comes the path to the
565+
# submodule
566+
path = line[1:].split(' ')[1]
567+
submodules.append([path, line[0]])
568+
569+
self.run(["git", "submodule", "sync"], cwd=self.rust_root)
570+
571+
for submod in submodules:
572+
path, status = submod
573+
if path.endswith(b"llvm") and \
574+
(self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT')):
575+
continue
576+
if path.endswith(b"jemalloc") and \
577+
(self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')):
578+
continue
579+
submod_path = os.path.join(self.rust_root, path)
580+
581+
if status == ' ':
582+
self.run(["git", "reset", "--hard"], cwd=submod_path)
583+
self.run(["git", "clean", "-fdx"], cwd=submod_path)
584+
elif status == '+':
585+
self.run(["git", "submodule", "update", path], cwd=self.rust_root)
586+
self.run(["git", "reset", "--hard"], cwd=submod_path)
587+
self.run(["git", "clean", "-fdx"], cwd=submod_path)
588+
elif status == '-':
589+
self.run(["git", "submodule", "init", path], cwd=self.rust_root)
590+
self.run(["git", "submodule", "update", path], cwd=self.rust_root)
591+
else:
592+
raise ValueError('unknown submodule status: ' + status)
593+
532594
def bootstrap():
533595
parser = argparse.ArgumentParser(description='Build rust')
534596
parser.add_argument('--config')
@@ -597,6 +659,8 @@ def bootstrap():
597659
else:
598660
rb._download_url = 'https://static.rust-lang.org'
599661

662+
rb.update_submodules()
663+
600664
# Fetch/build the bootstrap
601665
rb.build = rb.build_triple()
602666
rb.download_stage0()

‎src/bootstrap/lib.rs

Lines changed: 24 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ use std::env;
8282
use std::ffi::OsString;
8383
use std::fs::{self, File};
8484
use std::io::Read;
85-
use std::path::{Component, PathBuf, Path};
85+
use std::path::{PathBuf, Path};
8686
use std::process::Command;
8787

8888
use build_helper::{run_silent, run_suppressed, output, mtime};
@@ -285,129 +285,12 @@ impl Build {
285285
self.verbose(&format!("auto-detected local-rebuild {}", local_release));
286286
self.local_rebuild = true;
287287
}
288-
self.verbose("updating submodules");
289-
self.update_submodules();
290288
self.verbose("learning about cargo");
291289
metadata::build(self);
292290

293291
step::run(self);
294292
}
295293

296-
/// Updates all git submodules that we have.
297-
///
298-
/// This will detect if any submodules are out of date an run the necessary
299-
/// commands to sync them all with upstream.
300-
fn update_submodules(&self) {
301-
struct Submodule<'a> {
302-
path: &'a Path,
303-
state: State,
304-
}
305-
306-
enum State {
307-
// The submodule may have staged/unstaged changes
308-
MaybeDirty,
309-
// Or could be initialized but never updated
310-
NotInitialized,
311-
// The submodule, itself, has extra commits but those changes haven't been commited to
312-
// the (outer) git repository
313-
OutOfSync,
314-
}
315-
316-
if !self.src_is_git || !self.config.submodules {
317-
return
318-
}
319-
let git = || {
320-
let mut cmd = Command::new("git");
321-
cmd.current_dir(&self.src);
322-
return cmd
323-
};
324-
let git_submodule = || {
325-
let mut cmd = Command::new("git");
326-
cmd.current_dir(&self.src).arg("submodule");
327-
return cmd
328-
};
329-
330-
// FIXME: this takes a seriously long time to execute on Windows and a
331-
// nontrivial amount of time on Unix, we should have a better way
332-
// of detecting whether we need to run all the submodule commands
333-
// below.
334-
let out = output(git_submodule().arg("status"));
335-
let mut submodules = vec![];
336-
for line in out.lines() {
337-
// NOTE `git submodule status` output looks like this:
338-
//
339-
// -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc
340-
// +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..)
341-
// e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6)
342-
//
343-
// The first character can be '-', '+' or ' ' and denotes the `State` of the submodule
344-
// Right next to this character is the SHA-1 of the submodule HEAD
345-
// And after that comes the path to the submodule
346-
let path = Path::new(line[1..].split(' ').skip(1).next().unwrap());
347-
let state = if line.starts_with('-') {
348-
State::NotInitialized
349-
} else if line.starts_with('+') {
350-
State::OutOfSync
351-
} else if line.starts_with(' ') {
352-
State::MaybeDirty
353-
} else {
354-
panic!("unexpected git submodule state: {:?}", line.chars().next());
355-
};
356-
357-
submodules.push(Submodule { path: path, state: state })
358-
}
359-
360-
self.run(git_submodule().arg("sync"));
361-
362-
for submodule in submodules {
363-
// If using llvm-root then don't touch the llvm submodule.
364-
if submodule.path.components().any(|c| c == Component::Normal("llvm".as_ref())) &&
365-
self.config.target_config.get(&self.config.build)
366-
.and_then(|c| c.llvm_config.as_ref()).is_some()
367-
{
368-
continue
369-
}
370-
371-
if submodule.path.components().any(|c| c == Component::Normal("jemalloc".as_ref())) &&
372-
!self.config.use_jemalloc
373-
{
374-
continue
375-
}
376-
377-
// `submodule.path` is the relative path to a submodule (from the repository root)
378-
// `submodule_path` is the path to a submodule from the cwd
379-
380-
// use `submodule.path` when e.g. executing a submodule specific command from the
381-
// repository root
382-
// use `submodule_path` when e.g. executing a normal git command for the submodule
383-
// (set via `current_dir`)
384-
let submodule_path = self.src.join(submodule.path);
385-
386-
match submodule.state {
387-
State::MaybeDirty => {
388-
// drop staged changes
389-
self.run(git().current_dir(&submodule_path)
390-
.args(&["reset", "--hard"]));
391-
// drops unstaged changes
392-
self.run(git().current_dir(&submodule_path)
393-
.args(&["clean", "-fdx"]));
394-
},
395-
State::NotInitialized => {
396-
self.run(git_submodule().arg("init").arg(submodule.path));
397-
self.run(git_submodule().arg("update").arg(submodule.path));
398-
},
399-
State::OutOfSync => {
400-
// drops submodule commits that weren't reported to the (outer) git repository
401-
self.run(git_submodule().arg("update").arg(submodule.path));
402-
self.run(git().current_dir(&submodule_path)
403-
.args(&["reset", "--hard"]));
404-
self.run(git().current_dir(&submodule_path)
405-
.args(&["clean", "-fdx"]));
406-
},
407-
}
408-
}
409-
}
410-
411294
/// Clear out `dir` if `input` is newer.
412295
///
413296
/// After this executes, it will also ensure that `dir` exists.
@@ -475,12 +358,30 @@ impl Build {
475358
.env("RUSTDOC_REAL", self.rustdoc(compiler))
476359
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
477360

478-
// Tools don't get debuginfo right now, e.g. cargo and rls don't get
479-
// compiled with debuginfo.
480361
if mode != Mode::Tool {
481-
cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
482-
.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
483-
.env("RUSTC_FORCE_UNSTABLE", "1");
362+
// Tools don't get debuginfo right now, e.g. cargo and rls don't
363+
// get compiled with debuginfo.
364+
cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string())
365+
.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string())
366+
.env("RUSTC_FORCE_UNSTABLE", "1");
367+
368+
// Currently the compiler depends on crates from crates.io, and
369+
// then other crates can depend on the compiler (e.g. proc-macro
370+
// crates). Let's say, for example that rustc itself depends on the
371+
// bitflags crate. If an external crate then depends on the
372+
// bitflags crate as well, we need to make sure they don't
373+
// conflict, even if they pick the same verison of bitflags. We'll
374+
// want to make sure that e.g. a plugin and rustc each get their
375+
// own copy of bitflags.
376+
377+
// Cargo ensures that this works in general through the -C metadata
378+
// flag. This flag will frob the symbols in the binary to make sure
379+
// they're different, even though the source code is the exact
380+
// same. To solve this problem for the compiler we extend Cargo's
381+
// already-passed -C metadata flag with our own. Our rustc.rs
382+
// wrapper around the actual rustc will detect -C metadata being
383+
// passed and frob it with this extra string we're passing in.
384+
cargo.env("RUSTC_METADATA_SUFFIX", "rustc");
484385
}
485386

486387
// Enable usage of unstable features

‎src/tools/rust-installer

‎src/tools/tidy/src/deps.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static EXCEPTIONS: &'static [&'static str] = &[
3232
"openssl", // BSD+advertising clause, cargo, mdbook
3333
"pest", // MPL2, mdbook via handlebars
3434
"thread-id", // Apache-2.0, mdbook
35+
"strings", // this is actually MIT/Apache-2.0 but it's not in the manifest yet
3536
];
3637

3738
pub fn check(path: &Path, bad: &mut bool) {

0 commit comments

Comments
 (0)
Please sign in to comment.