Skip to content

Commit c542302

Browse files
committed
Add target-feature=[+-]crt-included.
This is supposed to support optionally using the system copy of musl libc instead of the included one if supported. This currently only affects the start files, which is enough to allow building rustc on musl targets.
1 parent ada45fd commit c542302

File tree

10 files changed

+112
-10
lines changed

10 files changed

+112
-10
lines changed

config.toml.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,14 @@
392392
# only use static libraries. If unset, the target's default linkage is used.
393393
#crt-static = false
394394

395+
# Force using the included C standard library for this target. If this target
396+
# is a host for rustc, this will also affect the linkage of the compiler
397+
# itself. This is useful for building rustc on targets that normally only use
398+
# the included C runtime. If unset, the target's default is used. This only
399+
# works if the linker for the target is targeting the corresponding C standard
400+
# library.
401+
#crt-included = true
402+
395403
# The root location of the MUSL installation directory. The library directory
396404
# will also need to contain libunwind.a for an unwinding implementation. Note
397405
# that this option only makes sense for MUSL targets that produce statically

src/bootstrap/bin/rustc.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,28 @@ fn main() {
235235
}
236236
}
237237

238+
let mut target_features = Vec::new();
239+
238240
if let Ok(s) = env::var("RUSTC_CRT_STATIC") {
239241
if s == "true" {
240-
cmd.arg("-C").arg("target-feature=+crt-static");
242+
target_features.push("+crt-static");
241243
}
242244
if s == "false" {
243-
cmd.arg("-C").arg("target-feature=-crt-static");
245+
target_features.push("-crt-static");
246+
}
247+
}
248+
249+
if let Ok(s) = env::var("RUSTC_CRT_INCLUDED") {
250+
if s == "true" {
251+
target_features.push("+crt-included");
244252
}
253+
if s == "false" {
254+
target_features.push("-crt-included");
255+
}
256+
}
257+
258+
if !target_features.is_empty() {
259+
cmd.arg("-C").arg(format!("target-feature={}", target_features.join(",")));
245260
}
246261

247262
// When running miri tests, we need to generate MIR for all libraries

src/bootstrap/builder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,10 @@ impl<'a> Builder<'a> {
663663
cargo.env("RUSTC_CRT_STATIC", x.to_string());
664664
}
665665

666+
if let Some(x) = self.crt_included(target) {
667+
cargo.env("RUSTC_CRT_INCLUDED", x.to_string());
668+
}
669+
666670
// Enable usage of unstable features
667671
cargo.env("RUSTC_BOOTSTRAP", "1");
668672
self.add_rust_test_threads(&mut cargo);

src/bootstrap/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ pub struct Target {
162162
pub linker: Option<PathBuf>,
163163
pub ndk: Option<PathBuf>,
164164
pub crt_static: Option<bool>,
165+
pub crt_included: Option<bool>,
165166
pub musl_root: Option<PathBuf>,
166167
pub qemu_rootfs: Option<PathBuf>,
167168
pub no_std: bool,
@@ -320,6 +321,7 @@ struct TomlTarget {
320321
linker: Option<String>,
321322
android_ndk: Option<String>,
322323
crt_static: Option<bool>,
324+
crt_included: Option<bool>,
323325
musl_root: Option<String>,
324326
qemu_rootfs: Option<String>,
325327
}
@@ -557,6 +559,7 @@ impl Config {
557559
target.ar = cfg.ar.clone().map(PathBuf::from);
558560
target.linker = cfg.linker.clone().map(PathBuf::from);
559561
target.crt_static = cfg.crt_static.clone();
562+
target.crt_included = cfg.crt_included.clone();
560563
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
561564
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
562565

src/bootstrap/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,11 @@ impl Build {
741741
}
742742
}
743743

744+
/// Returns if this target should use the included libc when linking
745+
fn crt_included(&self, target: Interned<String>) -> Option<bool> {
746+
self.config.target_config.get(&target).and_then(|t| t.crt_included)
747+
}
748+
744749
/// Returns the "musl root" for this `target`, if defined
745750
fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
746751
self.config.target_config.get(&target)

src/librustc/session/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,27 @@ impl Session {
657657
}
658658
}
659659

660+
pub fn crt_included(&self) -> bool {
661+
// If the target does not opt in to crt-included support, use its default.
662+
if self.target.target.options.crt_included_respected {
663+
self.crt_included_feature()
664+
} else {
665+
self.target.target.options.crt_included_default
666+
}
667+
}
668+
669+
pub fn crt_included_feature(&self) -> bool {
670+
let requested_features = self.opts.cg.target_feature.split(',');
671+
let found_negative = requested_features.clone().any(|r| r == "-crt-included");
672+
let found_positive = requested_features.clone().any(|r| r == "+crt-included");
673+
674+
if self.target.target.options.crt_included_default {
675+
!found_negative
676+
} else {
677+
found_positive
678+
}
679+
}
680+
660681
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
661682
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo
662683
|| !self.target.target.options.eliminate_frame_pointer

src/librustc_target/spec/linux_musl_base.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ 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!["-nostdlib".to_string()]);
1919

2020
// At least when this was tested, the linker would not add the
2121
// `GNU_EH_FRAME` program header to executables generated, which is required
@@ -55,14 +55,20 @@ pub fn opts() -> TargetOptions {
5555
//
5656
// Each target directory for musl has these object files included in it so
5757
// 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());
58+
base.pre_link_objects_exe_crt.push("crt1.o".to_string());
59+
base.pre_link_objects_exe_crt.push("crti.o".to_string());
60+
base.post_link_objects_crt.push("crtn.o".to_string());
6161

6262
// These targets statically link libc by default
6363
base.crt_static_default = true;
6464
// These targets allow the user to choose between static and dynamic linking.
6565
base.crt_static_respected = true;
6666

67+
// These targets support using an included libc instead of the system one
68+
// when linking.
69+
base.crt_included_default = true;
70+
// These targets can use the libc included with our standard library.
71+
base.crt_included_respected = true;
72+
6773
base
6874
}

src/librustc_target/spec/mod.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,23 @@ pub struct TargetOptions {
420420
/// Linker to invoke
421421
pub linker: Option<String>,
422422

423-
/// Linker arguments that are unconditionally passed *before* any
424-
/// user-defined libraries.
425-
pub pre_link_args: LinkArgs,
423+
/// Linker arguments that are passed *before* any user-defined libraries.
424+
pub pre_link_args: LinkArgs, // ... unconditionally
425+
pub pre_link_args_crt: LinkArgs, // ... with included-crt enabled
426426
/// Objects to link before all others, always found within the
427427
/// sysroot folder.
428428
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
429429
pub pre_link_objects_dll: Vec<String>, // ... when linking a dylib
430+
pub pre_link_objects_exe_crt: Vec<String>, // ... when linking an executable with included-crt
431+
// enabled
430432
/// Linker arguments that are unconditionally passed after any
431433
/// user-defined but before post_link_objects. Standard platform
432434
/// libraries that should be always be linked to, usually go here.
433435
pub late_link_args: LinkArgs,
434436
/// Objects to link after all others, always found within the
435437
/// sysroot folder.
436-
pub post_link_objects: Vec<String>,
438+
pub post_link_objects: Vec<String>, // ... unconditionally
439+
pub post_link_objects_crt: Vec<String>, // ... with included-crt enabled
437440
/// Linker arguments that are unconditionally passed *after* any
438441
/// user-defined libraries.
439442
pub post_link_args: LinkArgs,
@@ -578,6 +581,11 @@ pub struct TargetOptions {
578581
/// Whether or not crt-static is respected by the compiler (or is a no-op).
579582
pub crt_static_respected: bool,
580583

584+
/// Whether or not the CRT can be replaced with an included one.
585+
pub crt_included_default: bool,
586+
/// Whether or not the included-crt is respected by the compiler (or is a no-op).
587+
pub crt_included_respected: bool,
588+
581589
/// Whether or not stack probes (__rust_probestack) are enabled
582590
pub stack_probes: bool,
583591

@@ -633,6 +641,7 @@ impl Default for TargetOptions {
633641
is_builtin: false,
634642
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
635643
pre_link_args: LinkArgs::new(),
644+
pre_link_args_crt: LinkArgs::new(),
636645
post_link_args: LinkArgs::new(),
637646
asm_args: Vec::new(),
638647
cpu: "generic".to_string(),
@@ -667,7 +676,9 @@ impl Default for TargetOptions {
667676
relro_level: RelroLevel::None,
668677
pre_link_objects_exe: Vec::new(),
669678
pre_link_objects_dll: Vec::new(),
679+
pre_link_objects_exe_crt: Vec::new(),
670680
post_link_objects: Vec::new(),
681+
post_link_objects_crt: Vec::new(),
671682
late_link_args: LinkArgs::new(),
672683
link_env: Vec::new(),
673684
archive_format: "gnu".to_string(),
@@ -684,6 +695,8 @@ impl Default for TargetOptions {
684695
crt_static_allows_dylibs: false,
685696
crt_static_default: false,
686697
crt_static_respected: false,
698+
crt_included_default: false,
699+
crt_included_respected: false,
687700
stack_probes: false,
688701
min_global_align: None,
689702
default_codegen_units: None,
@@ -886,10 +899,13 @@ impl Target {
886899
key!(is_builtin, bool);
887900
key!(linker, optional);
888901
key!(pre_link_args, link_args);
902+
key!(pre_link_args_crt, link_args);
889903
key!(pre_link_objects_exe, list);
890904
key!(pre_link_objects_dll, list);
905+
key!(pre_link_objects_exe_crt, list);
891906
key!(late_link_args, link_args);
892907
key!(post_link_objects, list);
908+
key!(post_link_objects_crt, list);
893909
key!(post_link_args, link_args);
894910
key!(link_env, env);
895911
key!(asm_args, list);
@@ -936,6 +952,8 @@ impl Target {
936952
key!(crt_static_allows_dylibs, bool);
937953
key!(crt_static_default, bool);
938954
key!(crt_static_respected, bool);
955+
key!(crt_included_default, bool);
956+
key!(crt_included_respected, bool);
939957
key!(stack_probes, bool);
940958
key!(min_global_align, Option<u64>);
941959
key!(default_codegen_units, Option<u64>);
@@ -1091,10 +1109,13 @@ impl ToJson for Target {
10911109
target_option_val!(is_builtin);
10921110
target_option_val!(linker);
10931111
target_option_val!(link_args - pre_link_args);
1112+
target_option_val!(link_args - pre_link_args_crt);
10941113
target_option_val!(pre_link_objects_exe);
10951114
target_option_val!(pre_link_objects_dll);
1115+
target_option_val!(pre_link_objects_exe_crt);
10961116
target_option_val!(link_args - late_link_args);
10971117
target_option_val!(post_link_objects);
1118+
target_option_val!(post_link_objects_crt);
10981119
target_option_val!(link_args - post_link_args);
10991120
target_option_val!(env - link_env);
11001121
target_option_val!(asm_args);
@@ -1141,6 +1162,8 @@ impl ToJson for Target {
11411162
target_option_val!(crt_static_allows_dylibs);
11421163
target_option_val!(crt_static_default);
11431164
target_option_val!(crt_static_respected);
1165+
target_option_val!(crt_included_default);
1166+
target_option_val!(crt_included_respected);
11441167
target_option_val!(stack_probes);
11451168
target_option_val!(min_global_align);
11461169
target_option_val!(default_codegen_units);

src/librustc_trans/back/link.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,11 @@ fn link_natively(sess: &Session,
621621
if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
622622
cmd.args(args);
623623
}
624+
if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
625+
if sess.crt_included() {
626+
cmd.args(args);
627+
}
628+
}
624629
if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
625630
cmd.args(args);
626631
}
@@ -635,6 +640,12 @@ fn link_natively(sess: &Session,
635640
cmd.arg(root.join(obj));
636641
}
637642

643+
if crate_type == config::CrateTypeExecutable && sess.crt_included() {
644+
for obj in &sess.target.target.options.pre_link_objects_exe_crt {
645+
cmd.arg(root.join(obj));
646+
}
647+
}
648+
638649
if sess.target.target.options.is_like_emscripten {
639650
cmd.arg("-s");
640651
cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
@@ -656,6 +667,11 @@ fn link_natively(sess: &Session,
656667
for obj in &sess.target.target.options.post_link_objects {
657668
cmd.arg(root.join(obj));
658669
}
670+
if sess.crt_included() {
671+
for obj in &sess.target.target.options.post_link_objects_crt {
672+
cmd.arg(root.join(obj));
673+
}
674+
}
659675
if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
660676
cmd.args(args);
661677
}

src/librustc_trans/back/write.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ pub fn write_output_file(
126126
fn target_feature(sess: &Session) -> String {
127127
let rustc_features = [
128128
"crt-static",
129+
"crt-included",
129130
];
130131
let requested_features = sess.opts.cg.target_feature.split(',');
131132
let llvm_features = requested_features.filter(|f| {

0 commit comments

Comments
 (0)