Skip to content

Commit 48fda90

Browse files
trxcllntsylvestre
authored andcommitted
Fix and update sccache for CUDA 12.8
* cache (and dist-compile) cudafe++ invocations to ensure the original module_id file is restored and used for all PTX compilations * hash the module_id file (if it exists), `--gen_module_id_file` arg, and `--module_id_file_name` arg so PTX generated by `nvcc -c` and `nvcc -ptx` yield different hashes * remove `--gen_module_id_file` from internal cicc calls when using CTK<12.8 `nvcc -c`
1 parent b347f82 commit 48fda90

File tree

12 files changed

+403
-74
lines changed

12 files changed

+403
-74
lines changed

src/compiler/c.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ pub enum CCompilerKind {
155155
Msvc,
156156
/// NVIDIA CUDA compiler
157157
Nvcc,
158+
/// NVIDIA CUDA front-end
159+
CudaFE,
158160
/// NVIDIA CUDA optimizer and PTX generator
159161
Cicc,
160162
/// NVIDIA CUDA PTX assembler
@@ -1385,18 +1387,10 @@ impl pkg::ToolchainPackager for CToolchainPackager {
13851387
add_named_file(&mut package_builder, "liblto_plugin.so")?;
13861388
}
13871389

1388-
CCompilerKind::Cicc => {}
1389-
1390-
CCompilerKind::Ptxas => {}
1391-
1392-
CCompilerKind::Nvcc => {
1393-
// Various programs called by the nvcc front end.
1394-
// presumes the underlying host compiler is consistent
1395-
add_named_file(&mut package_builder, "cudafe++")?;
1396-
add_named_file(&mut package_builder, "fatbinary")?;
1397-
add_named_prog(&mut package_builder, "nvlink")?;
1398-
add_named_prog(&mut package_builder, "ptxas")?;
1399-
}
1390+
CCompilerKind::Cicc
1391+
| CCompilerKind::CudaFE
1392+
| CCompilerKind::Ptxas
1393+
| CCompilerKind::Nvcc => {}
14001394

14011395
CCompilerKind::Nvhpc => {
14021396
// Various programs called by the nvc nvc++ front end.

src/compiler/cicc.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl CCompilerImpl for Cicc {
5858
cwd: &Path,
5959
_env_vars: &[(OsString, OsString)],
6060
) -> CompilerArguments<ParsedArguments> {
61-
parse_arguments(arguments, cwd, Language::Ptx, &ARGS[..])
61+
parse_arguments(arguments, cwd, Language::Ptx, &ARGS[..], 3)
6262
}
6363
#[allow(clippy::too_many_arguments)]
6464
async fn preprocess<T>(
@@ -106,12 +106,13 @@ pub fn parse_arguments<S>(
106106
cwd: &Path,
107107
language: Language,
108108
arg_info: S,
109+
input_arg_offset_from_end: usize,
109110
) -> CompilerArguments<ParsedArguments>
110111
where
111112
S: SearchableArgInfo<ArgData>,
112113
{
113114
let mut args = arguments.to_vec();
114-
let input_loc = arguments.len() - 3;
115+
let input_loc = arguments.len() - input_arg_offset_from_end;
115116
let input = args.splice(input_loc..input_loc + 1, []).next().unwrap();
116117

117118
let mut take_next = false;
@@ -143,14 +144,18 @@ where
143144
);
144145
continue;
145146
}
146-
Some(UnhashedGenModuleIdFileFlag) => {
147+
Some(GenModuleIdFileFlag) => {
147148
take_next = false;
148149
gen_module_id_file = true;
149-
&mut unhashed_args
150+
&mut common_args
150151
}
151-
Some(UnhashedModuleIdFileName(o)) => {
152+
Some(ModuleIdFileName(o)) => {
152153
take_next = false;
153154
module_id_file_name = Some(cwd.join(o));
155+
&mut common_args
156+
}
157+
Some(UnhashedPassThrough(o)) => {
158+
take_next = false;
154159
&mut unhashed_args
155160
}
156161
Some(UnhashedOutput(o)) => {
@@ -220,8 +225,8 @@ where
220225
common_args,
221226
arch_args: vec![],
222227
unhashed_args,
223-
extra_dist_files,
224-
extra_hash_files: vec![],
228+
extra_dist_files: extra_dist_files.clone(),
229+
extra_hash_files: extra_dist_files,
225230
msvc_show_includes: false,
226231
profile_generate: false,
227232
color_mode: ColorMode::Off,
@@ -263,8 +268,6 @@ pub fn generate_compile_commands(
263268
let _ = path_transformer;
264269
}
265270

266-
trace!("compile");
267-
268271
let lang_str = &parsed_args.language.as_str();
269272
let out_file = match parsed_args.outputs.get("obj") {
270273
Some(obj) => &obj.path,
@@ -329,8 +332,9 @@ ArgData! { pub
329332
Output(PathBuf),
330333
PassThrough(OsString),
331334
UnhashedFlag,
332-
UnhashedGenModuleIdFileFlag,
333-
UnhashedModuleIdFileName(PathBuf),
335+
GenModuleIdFileFlag,
336+
ModuleIdFileName(PathBuf),
337+
UnhashedPassThrough(OsString),
334338
UnhashedOutput(PathBuf),
335339
}
336340

@@ -339,9 +343,9 @@ use self::ArgData::*;
339343
counted_array!(pub static ARGS: [ArgInfo<ArgData>; _] = [
340344
take_arg!("--gen_c_file_name", PathBuf, Separated, UnhashedOutput),
341345
take_arg!("--gen_device_file_name", PathBuf, Separated, UnhashedOutput),
342-
flag!("--gen_module_id_file", UnhashedGenModuleIdFileFlag),
346+
flag!("--gen_module_id_file", GenModuleIdFileFlag),
343347
take_arg!("--include_file_name", OsString, Separated, PassThrough),
344-
take_arg!("--module_id_file_name", PathBuf, Separated, UnhashedModuleIdFileName),
348+
take_arg!("--module_id_file_name", PathBuf, Separated, ModuleIdFileName),
345349
take_arg!("--stub_file_name", PathBuf, Separated, UnhashedOutput),
346350
take_arg!("-o", PathBuf, Separated, Output),
347351
]);

src/compiler/clang.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub fn language_to_clang_arg(lang: Language) -> Option<&'static str> {
188188
Language::ObjectiveCxx => Some("objective-c++"),
189189
Language::ObjectiveCxxHeader => Some("objective-c++-header"),
190190
Language::Cuda => Some("cuda"),
191+
Language::CudaFE => None,
191192
Language::Ptx => None,
192193
Language::Cubin => None,
193194
Language::Rust => None, // Let the compiler decide

src/compiler/compiler.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::compiler::args::*;
1818
use crate::compiler::c::{CCompiler, CCompilerKind};
1919
use crate::compiler::cicc::Cicc;
2020
use crate::compiler::clang::Clang;
21+
use crate::compiler::cudafe::CudaFE;
2122
use crate::compiler::diab::Diab;
2223
use crate::compiler::gcc::Gcc;
2324
use crate::compiler::msvc;
@@ -222,6 +223,7 @@ pub enum Language {
222223
ObjectiveCxx,
223224
ObjectiveCxxHeader,
224225
Cuda,
226+
CudaFE,
225227
Ptx,
226228
Cubin,
227229
Rust,
@@ -268,6 +270,7 @@ impl Language {
268270
Language::ObjectiveC => "objc",
269271
Language::ObjectiveCxx | Language::ObjectiveCxxHeader => "objc++",
270272
Language::Cuda => "cuda",
273+
Language::CudaFE => "cuda",
271274
Language::Ptx => "ptx",
272275
Language::Cubin => "cubin",
273276
Language::Rust => "rust",
@@ -288,6 +291,7 @@ impl CompilerKind {
288291
| Language::ObjectiveCxx
289292
| Language::ObjectiveCxxHeader => "C/C++",
290293
Language::Cuda => "CUDA",
294+
Language::CudaFE => "CUDA (Device code)",
291295
Language::Ptx => "PTX",
292296
Language::Cubin => "CUBIN",
293297
Language::Rust => "Rust",
@@ -303,6 +307,7 @@ impl CompilerKind {
303307
CompilerKind::C(CCompilerKind::Gcc) => textual_lang + " [gcc]",
304308
CompilerKind::C(CCompilerKind::Msvc) => textual_lang + " [msvc]",
305309
CompilerKind::C(CCompilerKind::Nvcc) => textual_lang + " [nvcc]",
310+
CompilerKind::C(CCompilerKind::CudaFE) => textual_lang + " [cudafe++]",
306311
CompilerKind::C(CCompilerKind::Cicc) => textual_lang + " [cicc]",
307312
CompilerKind::C(CCompilerKind::Ptxas) => textual_lang + " [ptxas]",
308313
CompilerKind::C(CCompilerKind::Nvhpc) => textual_lang + " [nvhpc]",
@@ -1165,6 +1170,17 @@ fn is_rustc_like<P: AsRef<Path>>(p: P) -> bool {
11651170
)
11661171
}
11671172

1173+
/// Returns true if the given path looks like cudafe++
1174+
fn is_nvidia_cudafe<P: AsRef<Path>>(p: P) -> bool {
1175+
matches!(
1176+
p.as_ref()
1177+
.file_stem()
1178+
.map(|s| s.to_string_lossy().to_lowercase())
1179+
.as_deref(),
1180+
Some("cudafe++")
1181+
)
1182+
}
1183+
11681184
/// Returns true if the given path looks like cicc
11691185
fn is_nvidia_cicc<P: AsRef<Path>>(p: P) -> bool {
11701186
matches!(
@@ -1248,6 +1264,18 @@ where
12481264

12491265
let rustc_executable = if let Some(ref rustc_executable) = maybe_rustc_executable {
12501266
rustc_executable
1267+
} else if is_nvidia_cudafe(executable) {
1268+
debug!("Found cudafe++");
1269+
return CCompiler::new(
1270+
CudaFE {
1271+
// TODO: Use nvcc --version
1272+
version: Some(String::new()),
1273+
},
1274+
executable.to_owned(),
1275+
&pool,
1276+
)
1277+
.await
1278+
.map(|c| (Box::new(c) as Box<dyn Compiler<T>>, None));
12511279
} else if is_nvidia_cicc(executable) {
12521280
debug!("Found cicc");
12531281
return CCompiler::new(

src/compiler/cudafe.rs

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// Copyright 2016 Mozilla Foundation
2+
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
#![allow(unused_imports, dead_code, unused_variables)]
17+
18+
use crate::compiler::args::*;
19+
use crate::compiler::c::{ArtifactDescriptor, CCompilerImpl, CCompilerKind, ParsedArguments};
20+
use crate::compiler::cicc;
21+
use crate::compiler::{
22+
CCompileCommand, Cacheable, ColorMode, CompileCommand, CompilerArguments, Language,
23+
SingleCompileCommand,
24+
};
25+
use crate::{counted_array, dist};
26+
27+
use crate::mock_command::{CommandCreator, CommandCreatorSync, RunCommand};
28+
29+
use async_trait::async_trait;
30+
31+
use std::collections::HashMap;
32+
use std::ffi::OsString;
33+
use std::fs;
34+
use std::path::{Path, PathBuf};
35+
use std::process;
36+
37+
use crate::errors::*;
38+
39+
/// A unit struct on which to implement `CCompilerImpl`.
40+
#[derive(Clone, Debug)]
41+
pub struct CudaFE {
42+
pub version: Option<String>,
43+
}
44+
45+
#[async_trait]
46+
impl CCompilerImpl for CudaFE {
47+
fn kind(&self) -> CCompilerKind {
48+
CCompilerKind::CudaFE
49+
}
50+
fn plusplus(&self) -> bool {
51+
true
52+
}
53+
fn version(&self) -> Option<String> {
54+
self.version.clone()
55+
}
56+
fn parse_arguments(
57+
&self,
58+
arguments: &[OsString],
59+
cwd: &Path,
60+
_env_vars: &[(OsString, OsString)],
61+
) -> CompilerArguments<ParsedArguments> {
62+
cicc::parse_arguments(arguments, cwd, Language::CudaFE, &ARGS[..], 1)
63+
}
64+
#[allow(clippy::too_many_arguments)]
65+
async fn preprocess<T>(
66+
&self,
67+
_creator: &T,
68+
_executable: &Path,
69+
parsed_args: &ParsedArguments,
70+
cwd: &Path,
71+
_env_vars: &[(OsString, OsString)],
72+
_may_dist: bool,
73+
_rewrite_includes_only: bool,
74+
_preprocessor_cache_mode: bool,
75+
) -> Result<process::Output>
76+
where
77+
T: CommandCreatorSync,
78+
{
79+
cicc::preprocess(cwd, parsed_args).await
80+
}
81+
fn generate_compile_commands<T>(
82+
&self,
83+
path_transformer: &mut dist::PathTransformer,
84+
executable: &Path,
85+
parsed_args: &ParsedArguments,
86+
cwd: &Path,
87+
env_vars: &[(OsString, OsString)],
88+
_rewrite_includes_only: bool,
89+
) -> Result<(
90+
Box<dyn CompileCommand<T>>,
91+
Option<dist::CompileCommand>,
92+
Cacheable,
93+
)>
94+
where
95+
T: CommandCreatorSync,
96+
{
97+
generate_compile_commands(path_transformer, executable, parsed_args, cwd, env_vars).map(
98+
|(command, dist_command, cacheable)| {
99+
(CCompileCommand::new(command), dist_command, cacheable)
100+
},
101+
)
102+
}
103+
}
104+
105+
pub fn generate_compile_commands(
106+
path_transformer: &mut dist::PathTransformer,
107+
executable: &Path,
108+
parsed_args: &ParsedArguments,
109+
cwd: &Path,
110+
env_vars: &[(OsString, OsString)],
111+
) -> Result<(
112+
SingleCompileCommand,
113+
Option<dist::CompileCommand>,
114+
Cacheable,
115+
)> {
116+
// Unused arguments
117+
#[cfg(not(feature = "dist-client"))]
118+
{
119+
let _ = path_transformer;
120+
}
121+
122+
let lang_str = &parsed_args.language.as_str();
123+
let out_file = match parsed_args.outputs.get("obj") {
124+
Some(obj) => &obj.path,
125+
None => return Err(anyhow!("Missing {:?} file output", lang_str)),
126+
};
127+
128+
let mut arguments: Vec<OsString> = vec![];
129+
arguments.extend_from_slice(&parsed_args.common_args);
130+
arguments.extend_from_slice(&parsed_args.unhashed_args);
131+
arguments.extend(vec![
132+
"--module_id_file_name".into(),
133+
out_file.into(),
134+
(&parsed_args.input).into(),
135+
]);
136+
137+
if log_enabled!(log::Level::Trace) {
138+
trace!(
139+
"[{}]: {} command: {:?}",
140+
out_file.file_name().unwrap().to_string_lossy(),
141+
executable.file_name().unwrap().to_string_lossy(),
142+
[
143+
&[format!("cd {} &&", cwd.to_string_lossy()).to_string()],
144+
&[executable.to_str().unwrap_or_default().to_string()][..],
145+
&dist::osstrings_to_strings(&arguments).unwrap_or_default()[..]
146+
]
147+
.concat()
148+
.join(" ")
149+
);
150+
}
151+
152+
let command = SingleCompileCommand {
153+
executable: executable.to_owned(),
154+
arguments,
155+
env_vars: env_vars.to_owned(),
156+
cwd: cwd.to_owned(),
157+
};
158+
159+
#[cfg(not(feature = "dist-client"))]
160+
let dist_command = None;
161+
#[cfg(feature = "dist-client")]
162+
let dist_command = (|| {
163+
let mut arguments: Vec<String> = vec![];
164+
arguments.extend(dist::osstrings_to_strings(&parsed_args.common_args)?);
165+
arguments.extend(dist::osstrings_to_strings(&parsed_args.unhashed_args)?);
166+
arguments.extend(vec![
167+
"--module_id_file_name".into(),
168+
path_transformer.as_dist(out_file)?,
169+
path_transformer.as_dist(&parsed_args.input)?,
170+
]);
171+
Some(dist::CompileCommand {
172+
executable: path_transformer.as_dist(executable.canonicalize().unwrap().as_path())?,
173+
arguments,
174+
env_vars: dist::osstring_tuples_to_strings(env_vars)?,
175+
cwd: path_transformer.as_dist_abs(cwd)?,
176+
})
177+
})();
178+
179+
Ok((command, dist_command, Cacheable::Yes))
180+
}
181+
182+
use cicc::ArgData::*;
183+
184+
counted_array!(pub static ARGS: [ArgInfo<cicc::ArgData>; _] = [
185+
take_arg!("--gen_c_file_name", PathBuf, Separated, UnhashedOutput),
186+
flag!("--gen_module_id_file", GenModuleIdFileFlag),
187+
take_arg!("--module_id_file_name", PathBuf, Separated, Output),
188+
take_arg!("--stub_file_name", OsString, Separated, UnhashedPassThrough),
189+
]);

0 commit comments

Comments
 (0)