Rollup merge of #114427 - Enselic:rustc_codegen_ssa-fixme, r=Nilstrieb

Handle non-utf8 rpaths (fix FIXME)

Removes a FIXME for #9639 which is closed since long ago.

Part of #44366 which is E-help-wanted.

(Also see https://github.com/rust-lang/rust/pull/114377)
This commit is contained in:
Matthias Krüger 2023-08-04 09:18:59 +02:00 committed by GitHub
commit 4fb44e59c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 32 deletions

View File

@ -1,6 +1,7 @@
use pathdiff::diff_paths; use pathdiff::diff_paths;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use std::env; use std::env;
use std::ffi::OsString;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -12,7 +13,7 @@ pub struct RPathConfig<'a> {
pub linker_is_gnu: bool, pub linker_is_gnu: bool,
} }
pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> { pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<OsString> {
// No rpath on windows // No rpath on windows
if !config.has_rpath { if !config.has_rpath {
return Vec::new(); return Vec::new();
@ -21,36 +22,38 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
debug!("preparing the RPATH!"); debug!("preparing the RPATH!");
let rpaths = get_rpaths(config); let rpaths = get_rpaths(config);
let mut flags = rpaths_to_flags(&rpaths); let mut flags = rpaths_to_flags(rpaths);
if config.linker_is_gnu { if config.linker_is_gnu {
// Use DT_RUNPATH instead of DT_RPATH if available // Use DT_RUNPATH instead of DT_RPATH if available
flags.push("-Wl,--enable-new-dtags".to_owned()); flags.push("-Wl,--enable-new-dtags".into());
// Set DF_ORIGIN for substitute $ORIGIN // Set DF_ORIGIN for substitute $ORIGIN
flags.push("-Wl,-z,origin".to_owned()); flags.push("-Wl,-z,origin".into());
} }
flags flags
} }
fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> { fn rpaths_to_flags(rpaths: Vec<OsString>) -> Vec<OsString> {
let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity
for rpath in rpaths { for rpath in rpaths {
if rpath.contains(',') { if rpath.to_string_lossy().contains(',') {
ret.push("-Wl,-rpath".into()); ret.push("-Wl,-rpath".into());
ret.push("-Xlinker".into()); ret.push("-Xlinker".into());
ret.push(rpath.clone()); ret.push(rpath);
} else { } else {
ret.push(format!("-Wl,-rpath,{}", &(*rpath))); let mut single_arg = OsString::from("-Wl,-rpath,");
single_arg.push(rpath);
ret.push(single_arg);
} }
} }
ret ret
} }
fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> { fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<OsString> {
debug!("output: {:?}", config.out_filename.display()); debug!("output: {:?}", config.out_filename.display());
debug!("libs:"); debug!("libs:");
for libpath in config.libs { for libpath in config.libs {
@ -64,18 +67,18 @@ fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> {
debug!("rpaths:"); debug!("rpaths:");
for rpath in &rpaths { for rpath in &rpaths {
debug!(" {}", rpath); debug!(" {:?}", rpath);
} }
// Remove duplicates // Remove duplicates
minimize_rpaths(&rpaths) minimize_rpaths(&rpaths)
} }
fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<String> { fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<OsString> {
config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect() config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
} }
fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> String { fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> OsString {
// Mac doesn't appear to support $ORIGIN // Mac doesn't appear to support $ORIGIN
let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" }; let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" };
@ -87,8 +90,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> Str
let output = fs::canonicalize(&output).unwrap_or(output); let output = fs::canonicalize(&output).unwrap_or(output);
let relative = path_relative_from(&lib, &output) let relative = path_relative_from(&lib, &output)
.unwrap_or_else(|| panic!("couldn't create relative path from {output:?} to {lib:?}")); .unwrap_or_else(|| panic!("couldn't create relative path from {output:?} to {lib:?}"));
// FIXME (#9639): This needs to handle non-utf8 paths
format!("{}/{}", prefix, relative.to_str().expect("non-utf8 component in path")) let mut rpath = OsString::from(prefix);
rpath.push("/");
rpath.push(relative);
rpath
} }
// This routine is adapted from the *old* Path's `path_relative_from` // This routine is adapted from the *old* Path's `path_relative_from`
@ -99,7 +105,7 @@ fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
diff_paths(path, base) diff_paths(path, base)
} }
fn minimize_rpaths(rpaths: &[String]) -> Vec<String> { fn minimize_rpaths(rpaths: &[OsString]) -> Vec<OsString> {
let mut set = FxHashSet::default(); let mut set = FxHashSet::default();
let mut minimized = Vec::new(); let mut minimized = Vec::new();
for rpath in rpaths { for rpath in rpaths {

View File

@ -1,32 +1,33 @@
use super::RPathConfig; use super::RPathConfig;
use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags}; use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags};
use std::ffi::OsString;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
#[test] #[test]
fn test_rpaths_to_flags() { fn test_rpaths_to_flags() {
let flags = rpaths_to_flags(&["path1".to_string(), "path2".to_string()]); let flags = rpaths_to_flags(vec!["path1".into(), "path2".into()]);
assert_eq!(flags, ["-Wl,-rpath,path1", "-Wl,-rpath,path2"]); assert_eq!(flags, ["-Wl,-rpath,path1", "-Wl,-rpath,path2"]);
} }
#[test] #[test]
fn test_minimize1() { fn test_minimize1() {
let res = minimize_rpaths(&["rpath1".to_string(), "rpath2".to_string(), "rpath1".to_string()]); let res = minimize_rpaths(&["rpath1".into(), "rpath2".into(), "rpath1".into()]);
assert!(res == ["rpath1", "rpath2",]); assert!(res == ["rpath1", "rpath2",]);
} }
#[test] #[test]
fn test_minimize2() { fn test_minimize2() {
let res = minimize_rpaths(&[ let res = minimize_rpaths(&[
"1a".to_string(), "1a".into(),
"2".to_string(), "2".into(),
"2".to_string(), "2".into(),
"1a".to_string(), "1a".into(),
"4a".to_string(), "4a".into(),
"1a".to_string(), "1a".into(),
"2".to_string(), "2".into(),
"3".to_string(), "3".into(),
"4a".to_string(), "4a".into(),
"3".to_string(), "3".into(),
]); ]);
assert!(res == ["1a", "2", "4a", "3",]); assert!(res == ["1a", "2", "4a", "3",]);
} }
@ -58,15 +59,15 @@ fn test_rpath_relative() {
#[test] #[test]
fn test_xlinker() { fn test_xlinker() {
let args = rpaths_to_flags(&["a/normal/path".to_string(), "a,comma,path".to_string()]); let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]);
assert_eq!( assert_eq!(
args, args,
vec![ vec![
"-Wl,-rpath,a/normal/path".to_string(), OsString::from("-Wl,-rpath,a/normal/path"),
"-Wl,-rpath".to_string(), OsString::from("-Wl,-rpath"),
"-Xlinker".to_string(), OsString::from("-Xlinker"),
"a,comma,path".to_string() OsString::from("a,comma,path")
] ]
); );
} }