Skip to content

Commit 3239eeb

Browse files
committed
strip prefix of temporary file names when it exceeds filesystem name length limit
When doing lto, rustc generates filenames that are concatenating many information. In the case of this testcase, it is concatenating crate name and rust file name, plus some hash, and the extension. In some other cases it will concatenate even more information reducing the maximum effective crate name to about 110 chars on linux filesystems where filename max length is 255 This commit is ensuring that the temporary file names are limited in size, while still reasonabily ensuring the unicity (with hashing of the stripped part)
1 parent dc0bae1 commit 3239eeb

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

compiler/rustc_session/src/config.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ use std::{cmp, fmt, fs, iter};
1616

1717
use externs::{ExternOpt, split_extern_opt};
1818
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
19-
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
19+
use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
2020
use rustc_errors::emitter::HumanReadableErrorType;
2121
use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg};
2222
use rustc_feature::UnstableFeatures;
23+
use rustc_hashes::Hash64;
2324
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
2425
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
2526
use rustc_span::source_map::FilePathMapping;
@@ -1198,7 +1199,25 @@ pub struct OutputFilenames {
11981199
pub const RLINK_EXT: &str = "rlink";
11991200
pub const RUST_CGU_EXT: &str = "rcgu";
12001201
pub const DWARF_OBJECT_EXT: &str = "dwo";
1202+
pub const MAX_FILENAME_LENGTH: usize = 143; // ecryptfs limits filenames to 143 bytes see #49914
12011203

1204+
/// Ensure the filename is not too long, as some filesystems have a limit.
1205+
/// If the filename is too long, hash part of it and append the hash to the filename.
1206+
/// This is a workaround for long crate names generating overly long filenames.
1207+
fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf {
1208+
if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH {
1209+
let filename = path.file_name().unwrap().to_string_lossy();
1210+
let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex
1211+
let stripped_len = filename.len() - MAX_FILENAME_LENGTH + hash_len;
1212+
1213+
let mut hasher = StableHasher::new();
1214+
filename[..stripped_len].hash(&mut hasher);
1215+
let hash = hasher.finish::<Hash64>();
1216+
1217+
path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..]));
1218+
}
1219+
path
1220+
}
12021221
impl OutputFilenames {
12031222
pub fn new(
12041223
out_directory: PathBuf,
@@ -1291,7 +1310,7 @@ impl OutputFilenames {
12911310
}
12921311

12931312
let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
1294-
self.with_directory_and_extension(temps_directory, &extension)
1313+
maybe_strip_file_name(self.with_directory_and_extension(temps_directory, &extension))
12951314
}
12961315

12971316
pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ no-prefer-dynamic
2+
3+
#![crate_type = "rlib"]
4+
5+
#[no_mangle]
6+
pub extern "C" fn foo() {}

tests/ui/lto/lto-large-crate-name.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This file has very long lines, but there is no way to avoid it as we are testing
2+
// long crate names. so:
3+
// ignore-tidy-linelength
4+
//@ build-pass
5+
//@ aux-build:lto-large-large-large-large-large-large-large-large-large-large-large-large-large-large-large-large-large-crate-name.rs
6+
//@ compile-flags: -C lto
7+
//@ no-prefer-dynamic
8+
extern crate lto_large_large_large_large_large_large_large_large_large_large_large_large_large_large_large_large_large_crate_name;
9+
10+
fn main() {}

0 commit comments

Comments
 (0)