Skip to content

Commit cdd72b7

Browse files
committed
[clang][cas] Avoid ingeting framework binaries into cas-fs for modules
When importing a framework module we check if the framework binary exists, and if so add an autolink for it. Ensure we canonicalize that file in the cas-fs rather than depending on the exact contents to avoid spurious cache misses every time a framework is rebuilt. (cherry picked from commit e76e221)
1 parent 34eb4b2 commit cdd72b7

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningCASFilesystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class DependencyScanningCASFilesystem : public llvm::cas::ThreadSafeFileSystem {
6363
createThreadSafeProxyFS() override;
6464

6565
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override;
66+
bool exists(const Twine &Path) override;
6667
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
6768
openFileForRead(const Twine &Path) override;
6869

clang/lib/Lex/ModuleMap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,8 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
962962
// for both before we give up.
963963
for (const char *extension : {"", ".tbd"}) {
964964
llvm::sys::path::replace_extension(LibName, extension);
965-
if (FileMgr.getFile(LibName)) {
965+
// Use VFS exists to avoid depending on the file's contents in cached builds
966+
if (FileMgr.getVirtualFileSystem().exists(LibName)) {
966967
Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
967968
/*IsFramework=*/true));
968969
return;

clang/lib/Tooling/DependencyScanning/DependencyScanningCASFilesystem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,13 @@ DependencyScanningCASFilesystem::status(const Twine &Path) {
299299
return Result.Entry->Status;
300300
}
301301

302+
bool DependencyScanningCASFilesystem::exists(const Twine &Path) {
303+
// Existence check does not require caching the result at the dependency
304+
// scanning level. The CachingOnDiskFileSystem tracks the exists call, which
305+
// ensures it is included in any resulting CASFileSystem.
306+
return getCachingFS().exists(Path);
307+
}
308+
302309
IntrusiveRefCntPtr<llvm::cas::ThreadSafeFileSystem>
303310
DependencyScanningCASFilesystem::createThreadSafeProxyFS() {
304311
llvm::report_fatal_error("not implemented");
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Check that when scanning framework modules, changing the framework binary
2+
// does not change the cache key.
3+
4+
// REQUIRES: ondisk_cas
5+
6+
// RUN: rm -rf %t
7+
// RUN: split-file %s %t
8+
// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
9+
10+
// RUN: clang-scan-deps -compilation-database %t/cdb.json \
11+
// RUN: -cas-path %t/cas -action-cache-path %t/cache -module-files-dir %t/outputs \
12+
// RUN: -format experimental-full -mode preprocess-dependency-directives \
13+
// RUN: > %t/deps_no_fw.json
14+
15+
// RUN: echo 'build 1' > %t/Foo.framework/Foo
16+
17+
// RUN: clang-scan-deps -compilation-database %t/cdb.json \
18+
// RUN: -cas-path %t/cas -action-cache-path %t/cache -module-files-dir %t/outputs \
19+
// RUN: -format experimental-full -mode preprocess-dependency-directives \
20+
// RUN: > %t/deps_fw1.json
21+
22+
// The existince of the framework is significant, since it affects autolinking.
23+
// RUN: not diff -u %t/deps_fw1.json %t/deps_fw2.json
24+
25+
// RUN: echo 'build 2' > %t/Foo.framework/Foo
26+
27+
// RUN: clang-scan-deps -compilation-database %t/cdb.json \
28+
// RUN: -cas-path %t/cas -action-cache-path %t/cache -module-files-dir %t/outputs \
29+
// RUN: -format experimental-full -mode preprocess-dependency-directives \
30+
// RUN: > %t/deps_fw2.json
31+
32+
// But the contents of the binary are not.
33+
// RUN: diff -u %t/deps_fw1.json %t/deps_fw2.json
34+
35+
//--- cdb.json.template
36+
[{
37+
"directory" : "DIR",
38+
"command" : "clang_tool -fsyntax-only DIR/tu.c -fmodules -fimplicit-modules -fimplicit-module-maps -fmodules-cache-path=DIR/module-cache -Rcompile-job-cache -F DIR",
39+
"file" : "DIR/tu.c"
40+
}]
41+
42+
//--- Foo.framework/Modules/module.modulemap
43+
framework module Foo {
44+
umbrella header "Foo.h"
45+
export *
46+
}
47+
48+
//--- Foo.framework/Headers/Foo.h
49+
50+
//--- tu.c
51+
#include "Foo/Foo.h"

0 commit comments

Comments
 (0)