From e8d2416fa425f848e8b99ea12982d53f8d454170 Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Wed, 24 Dec 2025 15:39:00 +0800 Subject: [PATCH] v1 --- compiler/rustc_codegen_ssa/src/back/linker.rs | 62 ++++++++++++++++--- compiler/rustc_codegen_ssa/src/base.rs | 6 +- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 + .../src/compiler-flags/cstyle-export-rules.md | 3 + 5 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/cstyle-export-rules.md diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 050797354b4a7..e8604e9a554ce 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -846,15 +846,31 @@ impl<'a> Linker for GccLinker<'a> { // Write an LD version script let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; - writeln!(f, "{{")?; - if !symbols.is_empty() { - writeln!(f, " global:")?; - for (sym, _) in symbols { - debug!(" {sym};"); - writeln!(f, " {sym};")?; + if self.sess.opts.unstable_opts.cstyle_export_rules { + writeln!(f, "{{")?; + writeln!(f, " global:\n *;\n")?; + if !symbols.is_empty() { + writeln!(f, " local:")?; + // writeln!(f, " _ZN*;")?; + // writeln!(f, " _R*;")?; + for (sym, _) in symbols { + debug!(" {sym};"); + writeln!(f, " {sym};")?; + } + } + writeln!(f, "\n}};")?; + } else { + writeln!(f, "{{")?; + if !symbols.is_empty() { + writeln!(f, " global:")?; + for (sym, _) in symbols { + debug!(" {sym};"); + writeln!(f, " {sym};")?; + } } + writeln!(f, "\n local:\n *;\n}};")?; } - writeln!(f, "\n local:\n *;\n}};")?; + }; if let Err(error) = res { self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); @@ -1812,6 +1828,38 @@ pub(crate) fn exported_symbols( } } +pub(crate) fn exported_symbols_cstyle( + tcx: TyCtxt<'_>, + crate_type: CrateType, +) -> Vec<(String, SymbolExportKind)> { + if let Some(ref exports) = tcx.sess.target.override_export_symbols { + return exports + .iter() + .map(|name| { + ( + name.to_string(), + // FIXME use the correct export kind for this symbol. override_export_symbols + // can't directly specify the SymbolExportKind as it is defined in rustc_middle + // which rustc_target can't depend on. + SymbolExportKind::Text, + ) + }) + .collect(); + } + + let mut symbols = Vec::new(); + let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); + for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { + if !info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) { + symbols.push(( + symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum), + info.kind, + )); + } + }); + symbols +} + fn exported_symbols_for_non_proc_macro( tcx: TyCtxt<'_>, crate_type: CrateType, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b4556ced0b3fb..cab667343085d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -876,7 +876,11 @@ impl CrateInfo { let crate_types = tcx.crate_types().to_vec(); let exported_symbols = crate_types .iter() - .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c))) + .map(|&c| (c, if tcx.sess.opts.unstable_opts.cstyle_export_rules { + crate::back::linker::exported_symbols_cstyle(tcx, c) + } else { + crate::back::linker::exported_symbols(tcx, c) + })) .collect(); let linked_symbols = crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 8771bb4405049..8afb3a9b06ed4 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -784,6 +784,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); + tracked!(cstyle_export_rules, true); tracked!(debug_info_for_profiling, true); tracked!(debug_info_type_line_numbers, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 44b35e8921ec3..41484dafdeec4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2176,6 +2176,8 @@ options! { "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), + cstyle_export_rules: bool = (false, parse_bool, [TRACKED], + "global symbols from upstream static libraries will be exported by default"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/cstyle-export-rules.md b/src/doc/unstable-book/src/compiler-flags/cstyle-export-rules.md new file mode 100644 index 0000000000000..c72db999645b1 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/cstyle-export-rules.md @@ -0,0 +1,3 @@ +# `cstyle-export-rules` + +This option forces rustc to export the `global` symbol from the upstream C static library. \ No newline at end of file