Skip to content

Commit a26ec54

Browse files
authored
[clang-scan-deps] Infer the tool locations from PATH (llvm#108539)
This allows the clang driver to know which tool is meant to be executed, which allows the clang driver to load the right clang config files, and allows clang to find colocated sysroots. This makes sure that doing `clang-scan-deps -- <tool> ...` looks up things in the same way as if one just would execute `<tool> ...`, when `<tool>` isn't an absolute or relative path.
1 parent 5130f32 commit a26ec54

12 files changed

+120
-16
lines changed

clang/include/clang/Tooling/CompilationDatabase.h

+6
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ std::unique_ptr<CompilationDatabase>
234234
std::unique_ptr<CompilationDatabase>
235235
inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
236236

237+
/// Returns a wrapped CompilationDatabase that will transform argv[0] to an
238+
/// absolute path, if it currently is a plain tool name, looking it up in
239+
/// PATH.
240+
std::unique_ptr<CompilationDatabase>
241+
inferToolLocation(std::unique_ptr<CompilationDatabase> Base);
242+
237243
/// Returns a wrapped CompilationDatabase that will expand all rsp(response)
238244
/// files on commandline returned by underlying database.
239245
std::unique_ptr<CompilationDatabase>

clang/lib/Tooling/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_clang_library(clangTooling
2525
GuessTargetAndModeCompilationDatabase.cpp
2626
InterpolatingCompilationDatabase.cpp
2727
JSONCompilationDatabase.cpp
28+
LocateToolCompilationDatabase.cpp
2829
Refactoring.cpp
2930
RefactoringCallbacks.cpp
3031
StandaloneExecution.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- GuessTargetAndModeCompilationDatabase.cpp --------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "clang/Tooling/CompilationDatabase.h"
10+
#include "clang/Tooling/Tooling.h"
11+
#include "llvm/Support/Path.h"
12+
#include "llvm/Support/Program.h"
13+
#include <memory>
14+
15+
namespace clang {
16+
namespace tooling {
17+
18+
namespace {
19+
class LocationAdderDatabase : public CompilationDatabase {
20+
public:
21+
LocationAdderDatabase(std::unique_ptr<CompilationDatabase> Base)
22+
: Base(std::move(Base)) {
23+
assert(this->Base != nullptr);
24+
}
25+
26+
std::vector<std::string> getAllFiles() const override {
27+
return Base->getAllFiles();
28+
}
29+
30+
std::vector<CompileCommand> getAllCompileCommands() const override {
31+
return addLocation(Base->getAllCompileCommands());
32+
}
33+
34+
std::vector<CompileCommand>
35+
getCompileCommands(StringRef FilePath) const override {
36+
return addLocation(Base->getCompileCommands(FilePath));
37+
}
38+
39+
private:
40+
std::vector<CompileCommand>
41+
addLocation(std::vector<CompileCommand> Cmds) const {
42+
for (auto &Cmd : Cmds) {
43+
if (Cmd.CommandLine.empty())
44+
continue;
45+
std::string &Driver = Cmd.CommandLine.front();
46+
// If the driver name already is absolute, we don't need to do anything.
47+
if (llvm::sys::path::is_absolute(Driver))
48+
continue;
49+
// If the name is a relative path, like bin/clang, we assume it's
50+
// possible to resolve it and don't do anything about it either.
51+
if (llvm::any_of(Driver,
52+
[](char C) { return llvm::sys::path::is_separator(C); }))
53+
continue;
54+
auto Absolute = llvm::sys::findProgramByName(Driver);
55+
// If we found it in path, update the entry in Cmd.CommandLine
56+
if (Absolute && llvm::sys::path::is_absolute(*Absolute))
57+
Driver = std::move(*Absolute);
58+
}
59+
return Cmds;
60+
}
61+
std::unique_ptr<CompilationDatabase> Base;
62+
};
63+
} // namespace
64+
65+
std::unique_ptr<CompilationDatabase>
66+
inferToolLocation(std::unique_ptr<CompilationDatabase> Base) {
67+
return std::make_unique<LocationAdderDatabase>(std::move(Base));
68+
}
69+
70+
} // namespace tooling
71+
} // namespace clang

clang/test/ClangScanDeps/modules-extern-submodule.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ module third {}
112112
// CHECK: "-fmodule-map-file=[[PREFIX]]/first/first/module.modulemap",
113113
// CHECK: "-fmodule-file=first=[[PREFIX]]/cache/{{.*}}/first-{{.*}}.pcm",
114114
// CHECK: ],
115-
// CHECK-NEXT: "executable": "clang",
116-
// CHECK-NEXT: "file-deps": [
115+
// CHECK: "file-deps": [
117116
// CHECK-NEXT: "[[PREFIX]]/tu.m"
118117
// CHECK-NEXT: ],
119118
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"

clang/test/ClangScanDeps/modules-full-output-tu-order.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
// CHECK: "-D"
3636
// CHECK-NEXT: "ONE"
3737
// CHECK: ],
38-
// CHECK-NEXT: "executable": "clang",
39-
// CHECK-NEXT: "file-deps": [
38+
// CHECK: "file-deps": [
4039
// CHECK-NEXT: "[[PREFIX]]/tu.c"
4140
// CHECK-NEXT: ],
4241
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"
@@ -52,8 +51,7 @@
5251
// CHECK: "-D"
5352
// CHECK-NEXT: "TWO"
5453
// CHECK: ],
55-
// CHECK-NEXT: "executable": "clang",
56-
// CHECK-NEXT: "file-deps": [
54+
// CHECK: "file-deps": [
5755
// CHECK-NEXT: "[[PREFIX]]/tu.c"
5856
// CHECK-NEXT: ],
5957
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"

clang/test/ClangScanDeps/modules-has-include-umbrella-header.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ module Dependency { header "dependency.h" }
6464
// CHECK: ],
6565
// CHECK-NEXT: "command-line": [
6666
// CHECK: ],
67-
// CHECK-NEXT: "executable": "clang",
68-
// CHECK-NEXT: "file-deps": [
67+
// CHECK: "file-deps": [
6968
// CHECK-NEXT: "[[PREFIX]]/tu.c"
7069
// CHECK-NEXT: ],
7170
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"

clang/test/ClangScanDeps/modules-header-sharing.m

+1-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@
7777
// CHECK: "-fmodule-map-file=[[PREFIX]]/frameworks/A.framework/Modules/module.modulemap",
7878
// CHECK: "-fmodule-name=A",
7979
// CHECK: ],
80-
// CHECK-NEXT: "executable": "clang",
81-
// CHECK-NEXT: "file-deps": [
80+
// CHECK: "file-deps": [
8281
// CHECK-NEXT: "[[PREFIX]]/tu.m",
8382
// CHECK-NEXT: "[[PREFIX]]/shared/H.h"
8483
// CHECK-NEXT: ],

clang/test/ClangScanDeps/modules-implementation-module-map.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ framework module FWPrivate { header "private.h" }
2727
// CHECK: "-fmodule-map-file=[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
2828
// CHECK: "-fmodule-name=FWPrivate",
2929
// CHECK: ],
30-
// CHECK-NEXT: "executable": "clang",
31-
// CHECK-NEXT: "file-deps": [
30+
// CHECK: "file-deps": [
3231
// CHECK-NEXT: "[[PREFIX]]/tu.m"
3332
// CHECK-NEXT: ],
3433
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.m"

clang/test/ClangScanDeps/modules-implementation-private.m

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@
6262
// CHECK-NEXT: ],
6363
// CHECK-NEXT: "command-line": [
6464
// CHECK: ],
65-
// CHECK-NEXT: "executable": "clang",
66-
// CHECK-NEXT: "file-deps": [
65+
// CHECK: "file-deps": [
6766
// CHECK-NEXT: "[[PREFIX]]/tu.m",
6867
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Missed.h",
6968
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h"

clang/test/ClangScanDeps/modules-priv-fw-from-pub.m

+1-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@
110110
// CHECK-NEXT: ],
111111
// CHECK-NEXT: "command-line": [
112112
// CHECK: ],
113-
// CHECK-NEXT: "executable": "clang",
114-
// CHECK-NEXT: "file-deps": [
113+
// CHECK: "file-deps": [
115114
// CHECK-NEXT: "[[PREFIX]]/tu.m"
116115
// CHECK-NEXT: ],
117116
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.m"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// UNSUPPORTED: system-windows
2+
3+
// Check that we expand the executable name to an absolute path, when invoked
4+
// with a plain executable name, which is implied to be found in PATH.
5+
// REQUIRES: x86-registered-target
6+
7+
// RUN: rm -rf %t
8+
// RUN: mkdir -p %t/bin
9+
// RUN: ln -s %clang %t/bin/x86_64-w64-mingw32-clang
10+
// RUN: split-file %s %t
11+
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json
12+
13+
// Check that we can deduce this both when using a compilation database, and when using
14+
// a literal command line.
15+
16+
// RUN: env "PATH=%t/bin:%PATH%" clang-scan-deps -format experimental-full -compilation-database %t/cdb.json | FileCheck %s -DBASE=%/t
17+
18+
// RUN: env "PATH=%t/bin:%PATH%" clang-scan-deps -format experimental-full -- x86_64-w64-mingw32-clang %t/source.c -o %t/source.o | FileCheck %s -DBASE=%/t
19+
20+
// CHECK: "executable": "[[BASE]]/bin/x86_64-w64-mingw32-clang"
21+
22+
//--- cdb.json.in
23+
[
24+
{
25+
"directory": "DIR"
26+
"command": "x86_64-w64-mingw32-clang -c DIR/source.c -o DIR/source.o"
27+
"file": "DIR/source.c"
28+
},
29+
]
30+
31+
//--- source.c
32+
void func(void) {}

clang/tools/clang-scan-deps/ClangScanDeps.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
815815

816816
Compilations = inferTargetAndDriverMode(std::move(Compilations));
817817

818+
Compilations = inferToolLocation(std::move(Compilations));
819+
818820
// The command options are rewritten to run Clang in preprocessor only mode.
819821
auto AdjustingCompilations =
820822
std::make_unique<tooling::ArgumentsAdjustingCompilations>(

0 commit comments

Comments
 (0)