Skip to content

Commit 4ecf12b

Browse files
committed
Auto merge of rust-lang#51063 - mixi:musl-bootstrap, r=alexcrichton
Fix building rustc on and for musl hosts. This fixes all problems I had when trying to compile rustc on a musl-based distribution (with `crt-static = false` in `config.toml`). This is a fixed version of what ended up being rust-lang#50105, making it possible to compile rustc on musl targets. The differences to the old (now merged and subsequently reverted) pull request are: - The commit (6d9154a) that caused the regression for which the original commits were reverted in rust-lang#50709 is left out. This means the corresponding bug rust-lang#36710 is still not fixed with `+crt-static`. - The test for issue 36710 is skipped for musl targets (until the issue is properly fixed). - Building cargo-vendor if `crt-static = false` is needed was broken (cargo-vendor links to some shared libraries if they exist on the system and this produces broken binaries with `+crt-static`) CC @alexcrichton
2 parents d830f46 + a8be9bd commit 4ecf12b

File tree

12 files changed

+165
-23
lines changed

12 files changed

+165
-23
lines changed

src/bootstrap/bin/rustc.rs

+9
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,15 @@ fn main() {
268268
if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
269269
cmd.arg(format!("-Clinker={}", host_linker));
270270
}
271+
272+
if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
273+
if s == "true" {
274+
cmd.arg("-C").arg("target-feature=+crt-static");
275+
}
276+
if s == "false" {
277+
cmd.arg("-C").arg("target-feature=-crt-static");
278+
}
279+
}
271280
}
272281

273282
if env::var_os("RUSTC_PARALLEL_QUERIES").is_some() {

src/bootstrap/bootstrap.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ def bin_root(self):
489489
"""
490490
return os.path.join(self.build_dir, self.build, "stage0")
491491

492-
def get_toml(self, key):
492+
def get_toml(self, key, section=None):
493493
"""Returns the value of the given key in config.toml, otherwise returns None
494494
495495
>>> rb = RustBuild()
@@ -501,12 +501,29 @@ def get_toml(self, key):
501501
502502
>>> rb.get_toml("key3") is None
503503
True
504+
505+
Optionally also matches the section the key appears in
506+
507+
>>> rb.config_toml = '[a]\\nkey = "value1"\\n[b]\\nkey = "value2"'
508+
>>> rb.get_toml('key', 'a')
509+
'value1'
510+
>>> rb.get_toml('key', 'b')
511+
'value2'
512+
>>> rb.get_toml('key', 'c') is None
513+
True
504514
"""
515+
516+
cur_section = None
505517
for line in self.config_toml.splitlines():
518+
section_match = re.match(r'^\s*\[(.*)\]\s*$', line)
519+
if section_match is not None:
520+
cur_section = section_match.group(1)
521+
506522
match = re.match(r'^{}\s*=(.*)$'.format(key), line)
507523
if match is not None:
508524
value = match.group(1)
509-
return self.get_string(value) or value.strip()
525+
if section is None or section == cur_section:
526+
return self.get_string(value) or value.strip()
510527
return None
511528

512529
def cargo(self):
@@ -589,7 +606,17 @@ def build_bootstrap(self):
589606
env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
590607
(os.pathsep + env["LIBRARY_PATH"]) \
591608
if "LIBRARY_PATH" in env else ""
592-
env["RUSTFLAGS"] = "-Cdebuginfo=2"
609+
env["RUSTFLAGS"] = "-Cdebuginfo=2 "
610+
611+
build_section = "target.{}".format(self.build_triple())
612+
target_features = []
613+
if self.get_toml("crt-static", build_section) == "true":
614+
target_features += ["+crt-static"]
615+
elif self.get_toml("crt-static", build_section) == "false":
616+
target_features += ["-crt-static"]
617+
if target_features:
618+
env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " "
619+
593620
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
594621
os.pathsep + env["PATH"]
595622
if not os.path.isfile(self.cargo()):

src/bootstrap/builder.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,14 @@ impl<'a> Builder<'a> {
698698
let out_dir = self.stage_out(compiler, mode);
699699
cargo
700700
.env("CARGO_TARGET_DIR", out_dir)
701-
.arg(cmd)
702-
.arg("--target")
703-
.arg(target);
701+
.arg(cmd);
702+
703+
if cmd != "install" {
704+
cargo.arg("--target")
705+
.arg(target);
706+
} else {
707+
assert_eq!(target, compiler.host);
708+
}
704709

705710
// Set a flag for `check` so that certain build scripts can do less work
706711
// (e.g. not building/requiring LLVM).
@@ -842,6 +847,10 @@ impl<'a> Builder<'a> {
842847
cargo.env("RUSTC_CRT_STATIC", x.to_string());
843848
}
844849

850+
if let Some(x) = self.crt_static(compiler.host) {
851+
cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
852+
}
853+
845854
// Enable usage of unstable features
846855
cargo.env("RUSTC_BOOTSTRAP", "1");
847856
self.add_rust_test_threads(&mut cargo);
@@ -1018,8 +1027,8 @@ impl<'a> Builder<'a> {
10181027
}
10191028

10201029
if self.config.rust_optimize {
1021-
// FIXME: cargo bench does not accept `--release`
1022-
if cmd != "bench" {
1030+
// FIXME: cargo bench/install do not accept `--release`
1031+
if cmd != "bench" && cmd != "install" {
10231032
cargo.arg("--release");
10241033
}
10251034
}

src/bootstrap/dist.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -951,13 +951,16 @@ impl Step for PlainSourceTarball {
951951
has_cargo_vendor |= line.starts_with("cargo-vendor ");
952952
}
953953
if !has_cargo_vendor {
954-
let mut cmd = Command::new(&builder.initial_cargo);
955-
cmd.arg("install")
956-
.arg("--force")
954+
let mut cmd = builder.cargo(
955+
builder.compiler(0, builder.config.build),
956+
Mode::Tool,
957+
builder.config.build,
958+
"install"
959+
);
960+
cmd.arg("--force")
957961
.arg("--debug")
958962
.arg("--vers").arg(CARGO_VENDOR_VERSION)
959-
.arg("cargo-vendor")
960-
.env("RUSTC", &builder.initial_rustc);
963+
.arg("cargo-vendor");
961964
if let Some(dir) = builder.openssl_install_dir(builder.config.build) {
962965
builder.ensure(native::Openssl {
963966
target: builder.config.build,

src/librustc_codegen_llvm/back/link.rs

+16
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,11 @@ fn link_natively(sess: &Session,
625625
if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
626626
cmd.args(args);
627627
}
628+
if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
629+
if sess.crt_static() {
630+
cmd.args(args);
631+
}
632+
}
628633
if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
629634
cmd.args(args);
630635
}
@@ -639,6 +644,12 @@ fn link_natively(sess: &Session,
639644
cmd.arg(root.join(obj));
640645
}
641646

647+
if crate_type == config::CrateTypeExecutable && sess.crt_static() {
648+
for obj in &sess.target.target.options.pre_link_objects_exe_crt {
649+
cmd.arg(root.join(obj));
650+
}
651+
}
652+
642653
if sess.target.target.options.is_like_emscripten {
643654
cmd.arg("-s");
644655
cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
@@ -660,6 +671,11 @@ fn link_natively(sess: &Session,
660671
for obj in &sess.target.target.options.post_link_objects {
661672
cmd.arg(root.join(obj));
662673
}
674+
if sess.crt_static() {
675+
for obj in &sess.target.target.options.post_link_objects_crt {
676+
cmd.arg(root.join(obj));
677+
}
678+
}
663679
if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
664680
cmd.args(args);
665681
}

src/librustc_target/spec/linux_musl_base.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ pub fn opts() -> TargetOptions {
1515

1616
// Make sure that the linker/gcc really don't pull in anything, including
1717
// default objects, libs, etc.
18-
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
18+
base.pre_link_args_crt.insert(LinkerFlavor::Gcc, Vec::new());
19+
base.pre_link_args_crt.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
1920

2021
// At least when this was tested, the linker would not add the
2122
// `GNU_EH_FRAME` program header to executables generated, which is required
@@ -55,9 +56,9 @@ pub fn opts() -> TargetOptions {
5556
//
5657
// Each target directory for musl has these object files included in it so
5758
// they'll be included from there.
58-
base.pre_link_objects_exe.push("crt1.o".to_string());
59-
base.pre_link_objects_exe.push("crti.o".to_string());
60-
base.post_link_objects.push("crtn.o".to_string());
59+
base.pre_link_objects_exe_crt.push("crt1.o".to_string());
60+
base.pre_link_objects_exe_crt.push("crti.o".to_string());
61+
base.post_link_objects_crt.push("crtn.o".to_string());
6162

6263
// These targets statically link libc by default
6364
base.crt_static_default = true;

src/librustc_target/spec/mod.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -426,20 +426,22 @@ pub struct TargetOptions {
426426
/// Linker to invoke
427427
pub linker: Option<String>,
428428

429-
/// Linker arguments that are unconditionally passed *before* any
430-
/// user-defined libraries.
431-
pub pre_link_args: LinkArgs,
429+
/// Linker arguments that are passed *before* any user-defined libraries.
430+
pub pre_link_args: LinkArgs, // ... unconditionally
431+
pub pre_link_args_crt: LinkArgs, // ... when linking with a bundled crt
432432
/// Objects to link before all others, always found within the
433433
/// sysroot folder.
434-
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
434+
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable, unconditionally
435+
pub pre_link_objects_exe_crt: Vec<String>, // ... when linking an executable with a bundled crt
435436
pub pre_link_objects_dll: Vec<String>, // ... when linking a dylib
436437
/// Linker arguments that are unconditionally passed after any
437438
/// user-defined but before post_link_objects. Standard platform
438439
/// libraries that should be always be linked to, usually go here.
439440
pub late_link_args: LinkArgs,
440441
/// Objects to link after all others, always found within the
441442
/// sysroot folder.
442-
pub post_link_objects: Vec<String>,
443+
pub post_link_objects: Vec<String>, // ... unconditionally
444+
pub post_link_objects_crt: Vec<String>, // ... when linking with a bundled crt
443445
/// Linker arguments that are unconditionally passed *after* any
444446
/// user-defined libraries.
445447
pub post_link_args: LinkArgs,
@@ -639,6 +641,7 @@ impl Default for TargetOptions {
639641
is_builtin: false,
640642
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
641643
pre_link_args: LinkArgs::new(),
644+
pre_link_args_crt: LinkArgs::new(),
642645
post_link_args: LinkArgs::new(),
643646
asm_args: Vec::new(),
644647
cpu: "generic".to_string(),
@@ -672,8 +675,10 @@ impl Default for TargetOptions {
672675
position_independent_executables: false,
673676
relro_level: RelroLevel::None,
674677
pre_link_objects_exe: Vec::new(),
678+
pre_link_objects_exe_crt: Vec::new(),
675679
pre_link_objects_dll: Vec::new(),
676680
post_link_objects: Vec::new(),
681+
post_link_objects_crt: Vec::new(),
677682
late_link_args: LinkArgs::new(),
678683
link_env: Vec::new(),
679684
archive_format: "gnu".to_string(),
@@ -892,10 +897,13 @@ impl Target {
892897
key!(is_builtin, bool);
893898
key!(linker, optional);
894899
key!(pre_link_args, link_args);
900+
key!(pre_link_args_crt, link_args);
895901
key!(pre_link_objects_exe, list);
902+
key!(pre_link_objects_exe_crt, list);
896903
key!(pre_link_objects_dll, list);
897904
key!(late_link_args, link_args);
898905
key!(post_link_objects, list);
906+
key!(post_link_objects_crt, list);
899907
key!(post_link_args, link_args);
900908
key!(link_env, env);
901909
key!(asm_args, list);
@@ -1097,10 +1105,13 @@ impl ToJson for Target {
10971105
target_option_val!(is_builtin);
10981106
target_option_val!(linker);
10991107
target_option_val!(link_args - pre_link_args);
1108+
target_option_val!(link_args - pre_link_args_crt);
11001109
target_option_val!(pre_link_objects_exe);
1110+
target_option_val!(pre_link_objects_exe_crt);
11011111
target_option_val!(pre_link_objects_dll);
11021112
target_option_val!(link_args - late_link_args);
11031113
target_option_val!(post_link_objects);
1114+
target_option_val!(post_link_objects_crt);
11041115
target_option_val!(link_args - post_link_args);
11051116
target_option_val!(env - link_env);
11061117
target_option_val!(asm_args);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-include ../tools.mk
2+
3+
ifeq (musl,$(findstring musl,$(TARGET)))
4+
all: skip
5+
else
6+
all: test
7+
endif
8+
9+
test: foo
10+
$(call RUN,foo)
11+
12+
skip:
13+
echo "expected failure"
14+
15+
foo: foo.rs $(call NATIVE_STATICLIB,foo)
16+
$(RUSTC) $< -lfoo $(EXTRACXXFLAGS)
17+
18+
$(TMPDIR)/libfoo.o: foo.cpp
19+
$(call COMPILE_OBJ_CXX,$@,$<)
20+
21+
.PHONY: all test skip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include <stdint.h>
12+
13+
struct A {
14+
A() { v = 1234; }
15+
~A() { v = 1; }
16+
uint32_t v;
17+
};
18+
19+
A a;
20+
21+
extern "C" {
22+
uint32_t get() {
23+
return a.v;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Tests that linking to C++ code with global destructors works.
12+
13+
extern { fn get() -> u32; }
14+
15+
fn main() {
16+
let i = unsafe { get() };
17+
assert_eq!(i, 1234);
18+
}

src/test/run-make-fulldeps/tools.mk

+2
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ endif
5959

6060
ifdef IS_MSVC
6161
COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
62+
COMPILE_OBJ_CXX = $(CXX) -c -Fo:`cygpath -w $(1)` $(2)
6263
NATIVE_STATICLIB_FILE = $(1).lib
6364
NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
6465
OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
6566
-Fo:`cygpath -w $(TMPDIR)/$(1).obj`
6667
else
6768
COMPILE_OBJ = $(CC) -c -o $(1) $(2)
69+
COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
6870
NATIVE_STATICLIB_FILE = lib$(1).a
6971
NATIVE_STATICLIB = $(call STATICLIB,$(1))
7072
OUT_EXE=-o $(TMPDIR)/$(1)

src/tools/compiletest/src/runtest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2529,7 +2529,7 @@ impl<'test> TestCx<'test> {
25292529
.env("IS_WINDOWS", "1")
25302530
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
25312531
.env("CC", format!("'{}' {}", self.config.cc, cflags))
2532-
.env("CXX", &self.config.cxx);
2532+
.env("CXX", format!("'{}'", &self.config.cxx));
25332533
} else {
25342534
cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
25352535
.env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))

0 commit comments

Comments
 (0)