Skip to content

Improve swift caching tests #71200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -1273,9 +1273,6 @@ def always_compile_output_files :
HelpText<"Always compile output files even it might not change the results">;

// CAS/Caching related options.
def allow_unstable_cache_key_for_testing: Flag<["-"], "allow-unstable-cache-key-for-testing">,
HelpText<"Allow compilation caching with unstable inputs for testing purpose">;

def input_file_key : Separate<["-"], "input-file-key">,
HelpText<"Cache Key for input file">;
def bridging_header_pch_key : Separate<["-"], "bridging-header-pch-key">,
Expand Down
6 changes: 2 additions & 4 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,8 @@ bool ArgsToFrontendOptionsConverter::convert(
if (Opts.EnableCaching && Opts.CASFSRootIDs.empty() &&
Opts.ClangIncludeTrees.empty() &&
FrontendOptions::supportCompilationCaching(Opts.RequestedAction)) {
if (!Args.hasArg(OPT_allow_unstable_cache_key_for_testing)) {
Diags.diagnose(SourceLoc(), diag::error_caching_no_cas_fs);
return true;
}
Diags.diagnose(SourceLoc(), diag::error_caching_no_cas_fs);
return true;
}

if (FrontendOptions::doesActionGenerateIR(Opts.RequestedAction)) {
Expand Down
27 changes: 17 additions & 10 deletions test/CAS/Inputs/BuildCommandExtractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,22 @@
mode = 'swiftPrebuiltExternal'
module_name = module_name[22:]


def printCmd(cmd):
for c in cmd:
print('"{}"'.format(c))


with open(input_json, 'r') as file:
deps = json.load(file)
module_names = deps['modules'][::2]
module_details = deps['modules'][1::2]
for name, detail in zip(module_names, module_details):
if name.get(mode, '') != module_name:
continue

cmd = detail['details'][mode]['commandLine']
for c in cmd:
print('"{}"'.format(c))
break
if module_name == 'bridgingHeader':
cmd = deps['modules'][1]['details']['swift']['bridgingHeader']['commandLine']
printCmd(cmd)
else:
module_names = deps['modules'][::2]
module_details = deps['modules'][1::2]
for name, detail in zip(module_names, module_details):
if name.get(mode, '') != module_name:
continue

printCmd(detail['details'][mode]['commandLine'])
11 changes: 5 additions & 6 deletions test/CAS/Inputs/ExtractOutputKey.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#!/usr/bin/env python3
#
# Usage: ExtractOutputKey.py file.json OutputPath
# Usage: ExtractOutputKey.py file.json InputPath

import json
import sys

input_json = sys.argv[1]
output_path = sys.argv[2]
input_path = sys.argv[2]


with open(input_json, 'r') as file:
entries = json.load(file)
for entry in entries:
for output in entry["Outputs"]:
if output['Path'] != output_path:
continue
print(entry['CacheKey'])
if entry['Input'] != input_path:
continue
print(entry['CacheKey'])
36 changes: 36 additions & 0 deletions test/CAS/Inputs/GenerateExplicitModuleMap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
#
# Usage: GenerateExplicitModuleMap.py file.json

import json
import sys

input_json = sys.argv[1]

modules = []

with open(input_json, 'r') as file:
deps = json.load(file)
main_module_name = deps['mainModuleName']
module_names = deps['modules'][::2]
module_details = deps['modules'][1::2]
# add all modules other than the main module into the module map.
for name, detail in zip(module_names, module_details):
kind, name = list(name.items())[0]
if name == main_module_name:
continue

module = {}
module["moduleName"] = name
module["isFramework"] = False
if kind == "clang":
module["clangModulePath"] = name + ".pcm"
module["clangModuleCacheKey"] = detail['details'][kind]["moduleCacheKey"]
else:
module["modulePath"] = name + ".swiftmdoule"
module["moduleCacheKey"] = detail['details'][kind]["moduleCacheKey"]

modules.append(module)


json.dump(modules, sys.stdout, indent=2)
62 changes: 44 additions & 18 deletions test/CAS/cache_key_compute.swift
Original file line number Diff line number Diff line change
@@ -1,56 +1,77 @@
// RUN: %empty-directory(%t)
// RUN: mkdir -p %t/cas
// RUN: split-file %s %t

// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
// RUN: %t/a.swift %t/b.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas

// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid

// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-parse-stdlib\"" >> %t/MyApp.cmd

/// Doesn't run because the command doesn't have CAS enabled.
// RUN: not %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend %s -c -allow-unstable-cache-key-for-testing 2>&1 | \
// RUN: %target-swift-frontend %t/a.swift -c @%t/MyApp.cmd 2>&1 | \
// RUN: %FileCheck %s --check-prefix=NO-CAS

// NO-CAS: Requested command-line arguments do not enable CAS

/// Check few working cases.
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job %s -c -allow-unstable-cache-key-for-testing > %t1.casid
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -c @%t/MyApp.cmd > %t1.casid
/// A different CAS doesn't affect base key.
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job %s -c -allow-unstable-cache-key-for-testing -cas-path %t > %t2.casid
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -c @%t/MyApp.cmd -cas-path %t > %t2.casid
/// Output path doesn't affect base key.
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job %s -c -allow-unstable-cache-key-for-testing -o %t/test.o > %t3.casid
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -c @%t/MyApp.cmd -o %t/test.o > %t3.casid
/// Add -D will change.
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job %s -c -allow-unstable-cache-key-for-testing -DTEST > %t4.casid
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -c @%t/MyApp.cmd -DTEST > %t4.casid

// RUN: diff %t1.casid %t2.casid
// RUN: diff %t1.casid %t3.casid
// RUN: not diff %t1.casid %t4.casid

/// Check filelist option.
// RUN: echo "%s" > %t/filelist-1
// RUN: echo "%s" > %t/filelist-2
// RUN: cp %s %t/temp.swift
// RUN: echo "%t/temp.swift" > %t/filelist-3
// RUN: echo "%t/a.swift" > %t/filelist-1
// RUN: echo "%t/a.swift" > %t/filelist-2
// RUN: echo "%t/b.swift" > %t/filelist-3
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-1 -c -allow-unstable-cache-key-for-testing > %t5.casid
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-1 -c @%t/MyApp.cmd > %t5.casid
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-2 -c -allow-unstable-cache-key-for-testing > %t6.casid
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-2 -c @%t/MyApp.cmd > %t6.casid
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-base-key -- \
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-3 -c -allow-unstable-cache-key-for-testing > %t7.casid
// RUN: %target-swift-frontend -cache-compile-job -filelist %t/filelist-3 -c @%t/MyApp.cmd > %t7.casid
// RUN: diff %t5.casid %t6.casid
// RUN: not diff %t5.casid %t7.casid

/// Test output keys.
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \
// RUN: %target-swift-frontend -cache-compile-job %s -emit-module -c -emit-dependencies \
// RUN: -emit-tbd -emit-tbd-path %t/test.tbd -o %t/test.o -allow-unstable-cache-key-for-testing | %FileCheck %s
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -emit-module -c -emit-dependencies \
// RUN: -emit-tbd -emit-tbd-path %t/test.tbd -o %t/test.o @%t/MyApp.cmd | %FileCheck %s

/// Test plugin CAS.
// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
// RUN: %t/a.swift -o %t/plugin_deps.json -cache-compile-job -cas-path %t/cas -cas-plugin-path %llvm_libs_dir/libCASPluginTest%llvm_plugin_ext \
// RUN: -cas-plugin-option first-prefix=myfirst-

// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/plugin_deps.json > %t/plugin_map.json
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/plugin_map.json > %t/map.casid

// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/plugin_deps.json Test > %t/plugin_MyApp.cmd
// RUN: %cache-tool -cas-path %t/cas -cas-plugin-path %llvm_libs_dir/libCASPluginTest%llvm_plugin_ext \
// RUN: -cas-plugin-option first-prefix=myfirst- -cache-tool-action print-output-keys -- \
// RUN: %target-swift-frontend -cache-compile-job %s -emit-module -c -emit-dependencies \
// RUN: -emit-tbd -emit-tbd-path %t/test.tbd -o %t/test.o -allow-unstable-cache-key-for-testing | %FileCheck %s --check-prefix=CHECK --check-prefix=PLUGIN
// RUN: %target-swift-frontend -cache-compile-job %t/a.swift -emit-module -c -emit-dependencies \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
// RUN: -emit-tbd -emit-tbd-path %t/test.tbd -o %t/test.o @%t/plugin_MyApp.cmd | %FileCheck %s --check-prefix=CHECK --check-prefix=PLUGIN

// CHECK: "Input": "{{.*}}{{/|\\}}cache_key_compute.swift"
// CHECK: "Input": "{{.*}}{{/|\\}}a.swift"
// CHECK-NEXT: "CacheKey"
// PLUGIN-SAME: myfirst-llvmcas://

Expand Down Expand Up @@ -81,3 +102,8 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]

//--- a.swift
func a() {}

//--- b.swift
func b() {}
50 changes: 32 additions & 18 deletions test/CAS/cache_replay.swift
Original file line number Diff line number Diff line change
@@ -1,42 +1,56 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -module-cache-path %t/clang-module-cache \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
// RUN: %t/test.swift -I %t -o %t/deps.json -cache-compile-job -cas-path %t/cas

/// Check clang module
// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:Dummy > %t/dummy.cmd
// RUN: %swift_frontend_plain @%t/dummy.cmd -Rcache-compile-job 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: %swift_frontend_plain @%t/dummy.cmd -Rcache-compile-job 2>&1 | %FileCheck --check-prefix=CACHE-HIT-CLANG %s

// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid

// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-swift-modules\"" >> %t/MyApp.cmd
// RUN: echo "\"-parse-stdlib\"" >> %t/MyApp.cmd
// RUN: echo "\"-explicit-swift-module-map-file\"" >> %t/MyApp.cmd
// RUN: echo "\"@%t/map.casid\"" >> %t/MyApp.cmd

/// Run the command first time, expect cache miss.
/// FIXME: This command doesn't use `-cas-fs` so it is not a good cache entry. It is currently allowed so it is easier to write tests.
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s

/// Expect cache hit for second time.
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s

/// Expect cache miss a subset of outputs.
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s

/// Cache hit for retry.
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s

/// Skip cache
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job -cache-disable-replay %t/test.swift -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --allow-empty --check-prefix=SKIP-CACHE %s

/// Check clang module
// RUN: %target-swift-frontend -emit-pcm -module-name Dummy %t/module.modulemap -cache-compile-job -Rcache-compile-job -cas-path %t/cas \
// RUN: -allow-unstable-cache-key-for-testing -o %t/dummy.pcm 2>&1 | %FileCheck --allow-empty --check-prefix=CACHE-MISS %s
// RUN: %target-swift-frontend -emit-pcm -module-name Dummy %t/module.modulemap -cache-compile-job -Rcache-compile-job -cas-path %t/cas \
// RUN: -allow-unstable-cache-key-for-testing -o %t/dummy.pcm 2>&1 | %FileCheck --allow-empty --check-prefix=CACHE-HIT-CLANG %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job -cache-disable-replay %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --allow-empty --check-prefix=SKIP-CACHE %s

// CACHE-MISS: remark: cache miss for input
// CACHE-HIT: remark: replay output file '<cached-diagnostics>': key 'llvmcas://{{.*}}'
// CACHE-HIT: remark: replay output file '{{.*}}{{/|\\}}test.o': key 'llvmcas://{{.*}}'
// CACHE-HIT: remark: replay output file '{{.*}}{{/|\\}}Test.swiftmodule': key 'llvmcas://{{.*}}'
// CACHE-HIT-CLANG: remark: replay output file '<cached-diagnostics>': key 'llvmcas://{{.*}}'
// CACHE-HIT-CLANG: remark: replay output file '{{.*}}{{/|\\}}dummy.pcm': key 'llvmcas://{{.*}}'
// CACHE-HIT-CLANG: remark: replay output file '{{.*}}{{/|\\}}Dummy-{{.*}}.pcm': key 'llvmcas://{{.*}}'
// SKIP-CACHE-NOT: remark:

//--- test.swift
import Dummy
func testFunc() {}

//--- module.modulemap
Expand Down
24 changes: 18 additions & 6 deletions test/CAS/cache_replay_multiple_files.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
// RUN: %t/test.swift %t/foo.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas

// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid

// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd
// RUN: echo "\"-parse-stdlib\"" >> %t/MyApp.cmd

/// Test compile multiple inputs with batch mode.
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift %t/foo.swift -emit-module -o %t/Test.swiftmodule \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job -primary-file %t/test.swift %t/foo.swift -c -o %t/test.o \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -primary-file %t/foo.swift -c -o %t/foo.o \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s

/// Expect cache hit second time
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift %t/foo.swift -emit-module -o %t/Test.swiftmodule \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job -primary-file %t/test.swift %t/foo.swift -c -o %t/test.o \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %t/test.swift -primary-file %t/foo.swift -c -o %t/foo.o \
// RUN: -module-name Test -cas-path %t/cas -allow-unstable-cache-key-for-testing 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s

//--- test.swift
func testFunc() {}
Expand Down
Loading