Skip to content

Commit 6b9133b

Browse files
authored
Merge pull request #26977 from nkcsgexi/api-digester-use-builtin-baseline
swift-api-digester: teach the tool to find framework-specific baselines from relative path
2 parents a5d7b72 + 178e5d5 commit 6b9133b

File tree

7 files changed

+96
-18
lines changed

7 files changed

+96
-18
lines changed

test/api-digester/stability-stdlib-abi-with-asserts.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// REQUIRES: swift_stdlib_asserts
33
// RUN: %empty-directory(%t.tmp)
44
// mkdir %t.tmp/module-cache && mkdir %t.tmp/dummy.sdk
5-
// RUN: %api-digester -dump-sdk -module Swift -o %t.tmp/current-stdlib.json -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -abi -avoid-location
6-
// RUN: %api-digester -diagnose-sdk -input-paths %S/Inputs/stdlib-stable-abi.json -input-paths %t.tmp/current-stdlib.json -abi -o %t.tmp/changes.txt -v
5+
// RUN: %api-digester -diagnose-sdk -module Swift -o %t.tmp/changes.txt -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -abi -avoid-location
76
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-abi.without.asserts.swift.expected -o - > %t.tmp/stability-stdlib-abi.swift.expected
87
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-abi.asserts.additional.swift.expected -o - >> %t.tmp/stability-stdlib-abi.swift.expected
98
// RUN: %clang -E -P -x c %t.tmp/stability-stdlib-abi.swift.expected -o - | sed '/^\s*$/d' | sort > %t.tmp/stability-stdlib-abi.swift.expected.sorted
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// REQUIRES: OS=macosx
22
// RUN: %empty-directory(%t.tmp)
33
// mkdir %t.tmp/module-cache && mkdir %t.tmp/dummy.sdk
4-
// RUN: %api-digester -dump-sdk -module Swift -o %t.tmp/current-stdlib.json -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -avoid-location
5-
// RUN: %api-digester -diagnose-sdk -input-paths %S/Inputs/stdlib-stable.json -input-paths %t.tmp/current-stdlib.json -o %t.tmp/changes.txt -v
4+
// RUN: %api-digester -diagnose-sdk -module Swift -o %t.tmp/changes.txt -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -avoid-location
65
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-source.swift.expected -o - | sed '/^\s*$/d' | sort > %t.tmp/stability-stdlib-source.swift.expected
76
// RUN: %clang -E -P -x c %t.tmp/changes.txt -o - | sed '/^\s*$/d' | sort > %t.tmp/changes.txt.tmp
87
// RUN: diff -u %t.tmp/stability-stdlib-source.swift.expected %t.tmp/changes.txt.tmp

tools/swift-api-digester/ModuleAnalyzerNodes.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,8 @@ static StringRef getKeyContent(SDKContext &Ctx, KeyKind Kind) {
586586
SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx,
587587
llvm::yaml::MappingNode *Node) {
588588
static auto GetScalarString = [&](llvm::yaml::Node *N) -> StringRef {
589-
auto WithQuote = cast<llvm::yaml::ScalarNode>(N)->getRawValue();
590-
return WithQuote.substr(1, WithQuote.size() - 2);
589+
SmallString<64> Buffer;
590+
return Ctx.buffer(cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer));
591591
};
592592

593593
static auto getAsInt = [&](llvm::yaml::Node *N) -> int {
@@ -2102,7 +2102,6 @@ static parseJsonEmit(SDKContext &Ctx, StringRef FileName) {
21022102
// previously dumped.
21032103
void SwiftDeclCollector::deSerialize(StringRef Filename) {
21042104
auto Pair = parseJsonEmit(Ctx, Filename);
2105-
OwnedBuffers.push_back(std::move(Pair.first));
21062105
RootNode = std::move(Pair.second);
21072106
}
21082107

tools/swift-api-digester/ModuleAnalyzerNodes.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ class SDKContext {
230230
CIs.emplace_back(new CompilerInstance());
231231
return *CIs.back();
232232
}
233-
234233
template<class YAMLNodeTy, typename ...ArgTypes>
235234
void diagnose(YAMLNodeTy node, Diag<ArgTypes...> ID,
236235
typename detail::PassArgument<ArgTypes>::type... args) {
@@ -707,7 +706,6 @@ struct TypeInitInfo {
707706

708707
class SwiftDeclCollector: public VisibleDeclConsumer {
709708
SDKContext &Ctx;
710-
std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedBuffers;
711709
SDKNode *RootNode;
712710
llvm::SetVector<Decl*> KnownDecls;
713711
// Collected and sorted after we get all of them.

tools/swift-api-digester/swift-api-digester.cpp

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ static llvm::cl::list<std::string>
234234
PreferInterfaceForModules("use-interface-for-module", llvm::cl::ZeroOrMore,
235235
llvm::cl::desc("Prefer loading these modules via interface"),
236236
llvm::cl::cat(Category));
237+
238+
static llvm::cl::opt<std::string>
239+
BaselineFilePath("baseline-path",
240+
llvm::cl::desc("The path to the Json file that we should use as the baseline"),
241+
llvm::cl::cat(Category));
237242
} // namespace options
238243

239244
namespace {
@@ -2529,6 +2534,77 @@ static bool hasBaselineInput() {
25292534
!options::BaselineFrameworkPaths.empty() || !options::BaselineSDK.empty();
25302535
}
25312536

2537+
enum class ComparisonInputMode: uint8_t {
2538+
BothJson,
2539+
BaselineJson,
2540+
BothLoad,
2541+
};
2542+
2543+
static ComparisonInputMode checkComparisonInputMode() {
2544+
if (options::SDKJsonPaths.size() == 2)
2545+
return ComparisonInputMode::BothJson;
2546+
else if (hasBaselineInput())
2547+
return ComparisonInputMode::BothLoad;
2548+
else
2549+
return ComparisonInputMode::BaselineJson;
2550+
}
2551+
2552+
static SDKNodeRoot *getBaselineFromJson(const char *Main, SDKContext &Ctx) {
2553+
SwiftDeclCollector Collector(Ctx);
2554+
// If the baseline path has been given, honor that.
2555+
if (!options::BaselineFilePath.empty()) {
2556+
Collector.deSerialize(options::BaselineFilePath);
2557+
return Collector.getSDKRoot();
2558+
}
2559+
CompilerInvocation Invok;
2560+
llvm::StringSet<> Modules;
2561+
// We need to call prepareForDump to parse target triple.
2562+
if (prepareForDump(Main, Invok, Modules, true))
2563+
return nullptr;
2564+
2565+
assert(Modules.size() == 1 &&
2566+
"Cannot find builtin baseline for more than one module");
2567+
// The path of the swift-api-digester executable.
2568+
std::string ExePath = llvm::sys::fs::getMainExecutable(Main,
2569+
reinterpret_cast<void *>(&anchorForGetMainExecutable));
2570+
llvm::SmallString<128> BaselinePath(ExePath);
2571+
llvm::sys::path::remove_filename(BaselinePath); // Remove /swift-api-digester
2572+
llvm::sys::path::remove_filename(BaselinePath); // Remove /bin
2573+
llvm::sys::path::append(BaselinePath, "lib", "swift", "FrameworkABIBaseline",
2574+
Modules.begin()->getKey());
2575+
// Look for ABI or API baseline
2576+
if (Ctx.checkingABI())
2577+
llvm::sys::path::append(BaselinePath, "ABI");
2578+
else
2579+
llvm::sys::path::append(BaselinePath, "API");
2580+
// Look for deployment target specific baseline files.
2581+
auto Triple = Invok.getLangOptions().Target;
2582+
if (Triple.isMacCatalystEnvironment())
2583+
llvm::sys::path::append(BaselinePath, "iosmac.json");
2584+
else if (Triple.isMacOSX())
2585+
llvm::sys::path::append(BaselinePath, "macos.json");
2586+
else if (Triple.isiOS())
2587+
llvm::sys::path::append(BaselinePath, "iphoneos.json");
2588+
else if (Triple.isTvOS())
2589+
llvm::sys::path::append(BaselinePath, "appletvos.json");
2590+
else if (Triple.isWatchOS())
2591+
llvm::sys::path::append(BaselinePath, "watchos.json");
2592+
else {
2593+
llvm::errs() << "Unsupported triple target\n";
2594+
exit(1);
2595+
}
2596+
StringRef Path = BaselinePath.str();
2597+
if (!fs::exists(Path)) {
2598+
llvm::errs() << "Baseline at " << Path << " does not exist\n";
2599+
exit(1);
2600+
}
2601+
if (options::Verbose) {
2602+
llvm::errs() << "Using baseline at " << Path << "\n";
2603+
}
2604+
Collector.deSerialize(Path);
2605+
return Collector.getSDKRoot();
2606+
}
2607+
25322608
int main(int argc, char *argv[]) {
25332609
PROGRAM_START(argc, argv);
25342610
INITIALIZE_LLVM();
@@ -2550,33 +2626,40 @@ int main(int argc, char *argv[]) {
25502626
dumpSDKContent(InitInvok, Modules, options::OutputFile, Opts);
25512627
case ActionType::MigratorGen:
25522628
case ActionType::DiagnoseSDKs: {
2553-
bool CompareJson = options::SDKJsonPaths.size() == 2;
2554-
if (!CompareJson && !hasBaselineInput()) {
2555-
llvm::errs() << "Only two SDK versions can be compared\n";
2556-
llvm::cl::PrintHelpMessage();
2557-
return 1;
2558-
}
2629+
ComparisonInputMode Mode = checkComparisonInputMode();
25592630
llvm::StringSet<> protocolWhitelist;
25602631
if (!options::ProtReqWhiteList.empty()) {
25612632
if (readFileLineByLine(options::ProtReqWhiteList, protocolWhitelist))
25622633
return 1;
25632634
}
2564-
if (options::Action == ActionType::MigratorGen)
2635+
if (options::Action == ActionType::MigratorGen) {
2636+
assert(Mode == ComparisonInputMode::BothJson && "Only BothJson mode is supported");
25652637
return generateMigrationScript(options::SDKJsonPaths[0],
25662638
options::SDKJsonPaths[1],
25672639
options::OutputFile, IgnoredUsrs, Opts);
2568-
else if (CompareJson)
2640+
}
2641+
switch(Mode) {
2642+
case ComparisonInputMode::BothJson: {
25692643
return diagnoseModuleChange(options::SDKJsonPaths[0],
25702644
options::SDKJsonPaths[1],
25712645
options::OutputFile, Opts,
25722646
std::move(protocolWhitelist));
2573-
else {
2647+
}
2648+
case ComparisonInputMode::BaselineJson: {
2649+
SDKContext Ctx(Opts);
2650+
return diagnoseModuleChange(Ctx, getBaselineFromJson(argv[0], Ctx),
2651+
getSDKRoot(argv[0], Ctx, false),
2652+
options::OutputFile,
2653+
std::move(protocolWhitelist));
2654+
}
2655+
case ComparisonInputMode::BothLoad: {
25742656
SDKContext Ctx(Opts);
25752657
return diagnoseModuleChange(Ctx, getSDKRoot(argv[0], Ctx, true),
25762658
getSDKRoot(argv[0], Ctx, false),
25772659
options::OutputFile,
25782660
std::move(protocolWhitelist));
25792661
}
2662+
}
25802663
}
25812664
case ActionType::DeserializeSDK:
25822665
case ActionType::DeserializeDiffItems: {

0 commit comments

Comments
 (0)