[clang] [llvm] [clang-cl] Omit command line and workdir in CIFF CV debug info for reproducible builds. (PR #205736)
Vladimir Vereschaka via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 30 20:06:06 PDT 2026
https://github.com/vvereschaka updated https://github.com/llvm/llvm-project/pull/205736
>From 1d1c3be07515ddab31562ece6d96c8571cb32d11 Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <vvereschaka at accesssoftek.com>
Date: Tue, 30 Jun 2026 19:48:51 -0700
Subject: [PATCH 1/2] [clang-cl] Omit command line and workdir in CIFF CV debug
info for reproducible builds.
The command line can contain the arguments, such as the pathes or /pathmap options,
which could break a reproducible output for the object files. In addition to
`-gcodeview-commandline` option that drops the command line from the build info,
this patch adds a new `-gcodeview-cwd` option to exclude the current working
directory from the build info of the CodeView debug info sections.
Also it links `-gno-codeview-cwd` and `-gno-codeview-commandline` options with
CL's `/Brepro` option to match (partly) compiler behaviour with MSVC.
---
clang/include/clang/Basic/DebugOptions.def | 3 +++
clang/include/clang/Options/Options.td | 6 ++++++
clang/lib/CodeGen/BackendUtil.cpp | 1 +
clang/lib/Driver/ToolChains/Clang.cpp | 3 +++
clang/test/DebugInfo/Generic/codeview-buildinfo.c | 10 ++++++++++
clang/test/Driver/cl-options.c | 2 ++
llvm/include/llvm/MC/MCTargetOptions.h | 1 +
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 +++-
8 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def
index c9dd3f726e799..6cba505901146 100644
--- a/clang/include/clang/Basic/DebugOptions.def
+++ b/clang/include/clang/Basic/DebugOptions.def
@@ -122,6 +122,9 @@ DEBUGOPT(CodeViewGHash, 1, 0, Compatible)
/// Whether to emit the compiler path and command line into the CodeView debug information.
DEBUGOPT(CodeViewCommandLine, 1, 0, Compatible)
+/// Whether to emit the current working directory into the CodeView debug information.
+DEBUGOPT(CodeViewEmitCurrentWorkdir, 1, 0, Compatible)
+
/// Whether emit extra debug info for sample pgo profile collection.
DEBUGOPT(DebugInfoForProfiling, 1, 0, Compatible)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 3a3952a4397be..5441d4d1c986a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5153,6 +5153,12 @@ defm codeview_command_line : BoolOption<"g", "codeview-command-line",
NegFlag<SetFalse, [], [ClangOption], "Don't emit compiler path and command line into CodeView debug information">,
BothFlags<[], [ClangOption, CLOption, DXCOption, CC1Option]>>,
Group<g_flags_Group>;
+defm codeview_cwd : BoolOption<"g", "codeview-cwd",
+ CodeGenOpts<"CodeViewEmitCurrentWorkdir">, DefaultTrue,
+ PosFlag<SetTrue, [], [ClangOption], "Emit current working directory into CodeView debug information">,
+ NegFlag<SetFalse, [], [ClangOption], "Don't emit current working directory into CodeView debug information">,
+ BothFlags<[], [ClangOption, CLOption, DXCOption, CC1Option]>>,
+ Group<g_flags_Group>;
defm inline_line_tables : BoolGOption<"inline-line-tables",
CodeGenOpts<"NoInlineLineTables">, DefaultFalse,
NegFlag<SetTrue, [], [ClangOption, CC1Option],
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index e33480f6c6416..292ee4e0ce54e 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -548,6 +548,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
InputFiles.push_back(Input.getFile());
Options.MCOptions.CommandlineArgs = flattenClangCommandLine(
CodeGenOpts.CommandLineArgs, CodeGenOpts.MainFileName, InputFiles);
+ Options.MCOptions.EmitCurrentWorkdir = CodeGenOpts.CodeViewEmitCurrentWorkdir;
Options.MCOptions.AsSecureLogFile = CodeGenOpts.AsSecureLogFile;
Options.MCOptions.PPCUseFullRegisterNames =
CodeGenOpts.PPCUseFullRegisterNames;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index ad57d5d71b942..d419a314df657 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -9091,6 +9091,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
// This option does not allow the user redefinitions for these macros.
if (!HasNoDateTime)
CmdArgs.push_back("-init-datetime-macros=literalone");
+ // Omit tool, current workdir and command line in COFF CV debug section.
+ CmdArgs.push_back("-gno-codeview-command-line");
+ CmdArgs.push_back("-gno-codeview-cwd");
}
}
diff --git a/clang/test/DebugInfo/Generic/codeview-buildinfo.c b/clang/test/DebugInfo/Generic/codeview-buildinfo.c
index b930e3cc642c4..853ffde86b7a4 100644
--- a/clang/test/DebugInfo/Generic/codeview-buildinfo.c
+++ b/clang/test/DebugInfo/Generic/codeview-buildinfo.c
@@ -24,6 +24,9 @@
// RUN: cd %t.relpath && %clang_cl --target=i686-windows-msvc /c /Z7 /Fo:hello.obj -- hello.cpp
// RUN: llvm-pdbutil dump --types %t.relpath/hello.obj | FileCheck %s --check-prefix RELPATH
+// RUN: %clang_cl --target=i686-windows-msvc /Brepro /c /Z7 /Fo%t.obj -- %s
+// RUN: llvm-pdbutil dump --types %t.obj | FileCheck %s --check-prefix BREPRO
+
int main(void) { return 42; }
// CHECK: Types (.debug$T)
@@ -78,3 +81,10 @@ int main(void) { return 42; }
// RELPATH-NEXT: 0x{{.*}}: `
// RELPATH-NOT: {{hello\.cpp}}
// RELPATH-SAME: `
+
+// BREPRO: 0x{{.+}} | LF_BUILDINFO [size = {{.+}}]
+// BREPRO-NEXT: 0x{{.*}}: ``
+// BREPRO-NEXT: 0x{{.*}}: ``
+// BREPRO-NEXT: 0x{{.*}}: `{{.+[\\/]codeview-buildinfo\.c}}`
+// BREPRO-NEXT: 0x{{.*}}: ``
+// BREPRO-NEXT: 0x{{.*}}: ``
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index 63a423f5b3114..c77e697f684d3 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -584,6 +584,8 @@
// RUN: %clang_cl /Brepro- /Brepro /c '-###' -- %s 2>&1 | FileCheck -check-prefix=Brepro %s
// Brepro: "-mno-incremental-linker-compatible"
+// Brepro: "-gno-codeview-command-line"
+// Brepro: "-gno-codeview-cwd"
// RUN: %clang_cl /Brepro /Brepro- /c '-###' -- %s 2>&1 | FileCheck -check-prefix=Brepro_ %s
// Brepro_: "-mincremental-linker-compatible"
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index e3d1a8cc763b7..5451086b15833 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -102,6 +102,7 @@ class MCTargetOptions {
// Used for codeview debug info. These will be set as compiler path and commandline arguments in LF_BUILDINFO
std::string Argv0;
std::string CommandlineArgs;
+ bool EmitCurrentWorkdir : 1;
/// Additional paths to search for `.include` directives when using the
/// integrated assembler.
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 06353a0e039db..a63e40127f9fa 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -956,8 +956,10 @@ void CodeViewDebug::emitBuildInfo() {
const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
const auto *CU = cast<DICompileUnit>(Node);
const DIFile *MainSourceFile = CU->getFile();
+ const llvm::StringRef cwd = Asm->TM.Options.MCOptions.EmitCurrentWorkdir ?
+ MainSourceFile->getDirectory() : llvm::StringRef("");
BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
- getStringIdTypeIdx(TypeTable, MainSourceFile->getDirectory());
+ getStringIdTypeIdx(TypeTable, cwd);
BuildInfoArgs[BuildInfoRecord::SourceFile] =
getStringIdTypeIdx(TypeTable, MainSourceFile->getFilename());
// FIXME: PDB is intentionally blank unless we implement /Zi type servers.
>From 4cb6e336e52ea3c3f1463b0b3e4beaa904026c8d Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <vvereschaka at accesssoftek.com>
Date: Tue, 30 Jun 2026 20:05:41 -0700
Subject: [PATCH 2/2] Fix code formatting
---
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index a63e40127f9fa..8664eefc1b235 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -956,8 +956,9 @@ void CodeViewDebug::emitBuildInfo() {
const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
const auto *CU = cast<DICompileUnit>(Node);
const DIFile *MainSourceFile = CU->getFile();
- const llvm::StringRef cwd = Asm->TM.Options.MCOptions.EmitCurrentWorkdir ?
- MainSourceFile->getDirectory() : llvm::StringRef("");
+ const llvm::StringRef cwd = Asm->TM.Options.MCOptions.EmitCurrentWorkdir
+ ? MainSourceFile->getDirectory()
+ : llvm::StringRef("");
BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
getStringIdTypeIdx(TypeTable, cwd);
BuildInfoArgs[BuildInfoRecord::SourceFile] =
More information about the cfe-commits
mailing list