mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
swift-api-digester: teach the tool to compare two SDKs directly
With module stability from the compiler, we can now use an earlier version of the SDK as the baseline and compare the new SDK with it. This patch adds a new -bsdk flag to the tool to specify the baseline SDK path.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
#if !defined(__FOOSUB_H__)
|
||||
#define __FOOSUB_H__ 1
|
||||
|
||||
int fooSubFunc1(int a);
|
||||
|
||||
enum FooSubEnum1 {
|
||||
FooSubEnum1X,
|
||||
FooSubEnum1Y
|
||||
};
|
||||
|
||||
enum {
|
||||
FooSubUnnamedEnumeratorA1
|
||||
};
|
||||
|
||||
#endif /* ! __FOOSUB_H__ */
|
||||
@@ -0,0 +1,11 @@
|
||||
/* Foo.h
|
||||
Copyright (c) 1815, Napoleon Bonaparte. All rights reserved.
|
||||
*/
|
||||
#if !defined(__FOO_H__)
|
||||
#define __FOO_H__ 1
|
||||
|
||||
#import <FooSub/FooSub.h>
|
||||
|
||||
void removedFunction(void);
|
||||
|
||||
#endif /* ! __FOO_H__ */
|
||||
@@ -0,0 +1,9 @@
|
||||
framework module Foo {
|
||||
umbrella header "Foo.h"
|
||||
export *
|
||||
framework module FooSub {
|
||||
umbrella header "FooSub.h"
|
||||
export *
|
||||
}
|
||||
}
|
||||
|
||||
1
test/api-digester/Inputs/mock-sdk-modules.txt
Normal file
1
test/api-digester/Inputs/mock-sdk-modules.txt
Normal file
@@ -0,0 +1 @@
|
||||
Foo
|
||||
@@ -0,0 +1,15 @@
|
||||
#if !defined(__FOOSUB_H__)
|
||||
#define __FOOSUB_H__ 1
|
||||
|
||||
int fooSubFunc1(int a);
|
||||
|
||||
enum FooSubEnum1 {
|
||||
FooSubEnum1X,
|
||||
FooSubEnum1Y
|
||||
};
|
||||
|
||||
enum {
|
||||
FooSubUnnamedEnumeratorA1
|
||||
};
|
||||
|
||||
#endif /* ! __FOOSUB_H__ */
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Foo.h
|
||||
Copyright (c) 1815, Napoleon Bonaparte. All rights reserved.
|
||||
*/
|
||||
#if !defined(__FOO_H__)
|
||||
#define __FOO_H__ 1
|
||||
|
||||
#import <FooSub/FooSub.h>
|
||||
|
||||
#endif /* ! __FOO_H__ */
|
||||
@@ -0,0 +1,9 @@
|
||||
framework module Foo {
|
||||
umbrella header "Foo.h"
|
||||
export *
|
||||
framework module FooSub {
|
||||
umbrella header "FooSub.h"
|
||||
export *
|
||||
}
|
||||
}
|
||||
|
||||
1
test/api-digester/Outputs/mock-sdk-api.txt
Normal file
1
test/api-digester/Outputs/mock-sdk-api.txt
Normal file
@@ -0,0 +1 @@
|
||||
Foo(Foo.h): Func removedFunction() has been removed
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.mod1/cake.swiftinterface %S/Inputs/cake_baseline/cake.swift -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache
|
||||
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.mod2/cake.swiftinterface %S/Inputs/cake_current/cake.swift -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache
|
||||
// RUN: %api-digester -diagnose-sdk -print-module -module cake -BI %t.mod1 -BI %S/Inputs/APINotesLeft -I %t.mod2 -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource -module-cache-path %t.module-cache -o %t.result -abi
|
||||
// RUN: %api-digester -diagnose-sdk -print-module -module cake -BI %t.mod1 -BI %S/Inputs/APINotesLeft -I %t.mod2 -I %S/Inputs/APINotesRight -sdk %clang-importer-sdk-path -bsdk %clang-importer-sdk-path -module-cache-path %t.module-cache -o %t.result -abi
|
||||
|
||||
// RUN: %clang -E -P -x c %S/Outputs/Cake-abi.txt -o - | sed '/^\s*$/d' > %t.expected
|
||||
// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.mod1/cake.swiftinterface %S/Inputs/cake_baseline/cake.swift -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache
|
||||
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.mod2/cake.swiftinterface %S/Inputs/cake_current/cake.swift -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache
|
||||
// RUN: %api-digester -diagnose-sdk -print-module -module cake -BI %t.mod1 -BI %S/Inputs/APINotesLeft -I %t.mod2 -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource -module-cache-path %t.module-cache -o %t.result
|
||||
// RUN: %api-digester -diagnose-sdk -print-module -module cake -BI %t.mod1 -BI %S/Inputs/APINotesLeft -I %t.mod2 -I %S/Inputs/APINotesRight -sdk %clang-importer-sdk-path -bsdk %clang-importer-sdk-path -module-cache-path %t.module-cache -o %t.result
|
||||
|
||||
// RUN: %clang -E -P -x c %S/Outputs/Cake.txt -o - | sed '/^\s*$/d' > %t.expected
|
||||
// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
|
||||
|
||||
10
test/api-digester/compare-two-sdks.swift
Normal file
10
test/api-digester/compare-two-sdks.swift
Normal file
@@ -0,0 +1,10 @@
|
||||
// RUN: %empty-directory(%t.mod1)
|
||||
// RUN: %empty-directory(%t.mod2)
|
||||
// RUN: %empty-directory(%t.sdk)
|
||||
// RUN: %empty-directory(%t.module-cache)
|
||||
|
||||
// RUN: %api-digester -diagnose-sdk -print-module -module-list-file %S/Inputs/mock-sdk-modules.txt -sdk %S/Inputs/mock-sdk.sdk -bsdk %S/Inputs/mock-sdk-baseline.sdk -module-cache-path %t.module-cache -o %t.result
|
||||
|
||||
// RUN: %clang -E -P -x c %S/Outputs/mock-sdk-api.txt -o - | sed '/^\s*$/d' > %t.expected
|
||||
// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp
|
||||
// RUN: diff -u %t.expected %t.result.tmp
|
||||
@@ -81,6 +81,10 @@ static llvm::cl::opt<std::string>
|
||||
SDK("sdk", llvm::cl::desc("path to the SDK to build against"),
|
||||
llvm::cl::cat(Category));
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
BaselineSDK("bsdk", llvm::cl::desc("path to the baseline SDK to import frameworks"),
|
||||
llvm::cl::cat(Category));
|
||||
|
||||
static llvm::cl::opt<std::string>
|
||||
Triple("target", llvm::cl::desc("target triple"),
|
||||
llvm::cl::cat(Category));
|
||||
@@ -98,6 +102,10 @@ static llvm::cl::list<std::string>
|
||||
FrameworkPaths("F", llvm::cl::desc("add a directory to the framework search path"),
|
||||
llvm::cl::cat(Category));
|
||||
|
||||
static llvm::cl::list<std::string>
|
||||
BaselineFrameworkPaths("BF", llvm::cl::desc("add a directory to the baseline framework search path"),
|
||||
llvm::cl::cat(Category));
|
||||
|
||||
static llvm::cl::list<std::string>
|
||||
BaselineModuleInputPaths("BI", llvm::cl::desc("add a module for baseline input"),
|
||||
llvm::cl::cat(Category));
|
||||
@@ -2084,6 +2092,10 @@ static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule,
|
||||
assert(LeftModule);
|
||||
assert(RightModule);
|
||||
llvm::raw_ostream *OS = &llvm::errs();
|
||||
if (!LeftModule || !RightModule) {
|
||||
*OS << "Cannot diagnose null SDKNodeRoot";
|
||||
exit(1);
|
||||
}
|
||||
std::unique_ptr<llvm::raw_ostream> FileOS;
|
||||
if (!OutputPath.empty()) {
|
||||
std::error_code EC;
|
||||
@@ -2270,13 +2282,14 @@ static int readFileLineByLine(StringRef Path, llvm::StringSet<> &Lines) {
|
||||
// without being given the address of a function in the main executable).
|
||||
void anchorForGetMainExecutable() {}
|
||||
|
||||
static int prepareForDump(const char *Main,
|
||||
CompilerInvocation &InitInvok,
|
||||
llvm::StringSet<> &Modules,
|
||||
bool IsBaseline = false) {
|
||||
InitInvok.setMainExecutablePath(fs::getMainExecutable(Main,
|
||||
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
||||
InitInvok.setModuleName("swift_ide_test");
|
||||
static void setSDKPath(CompilerInvocation &InitInvok, bool IsBaseline) {
|
||||
if (IsBaseline) {
|
||||
// Set baseline SDK
|
||||
if (!options::BaselineSDK.empty()) {
|
||||
InitInvok.setSDKPath(options::BaselineSDK);
|
||||
}
|
||||
} else {
|
||||
// Set current SDK
|
||||
if (!options::SDK.empty()) {
|
||||
InitInvok.setSDKPath(options::SDK);
|
||||
} else if (const char *SDKROOT = getenv("SDKROOT")) {
|
||||
@@ -2284,8 +2297,19 @@ static int prepareForDump(const char *Main,
|
||||
} else {
|
||||
llvm::errs() << "Provide '-sdk <path>' option or run with 'xcrun -sdk <..>\
|
||||
swift-api-digester'\n";
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int prepareForDump(const char *Main,
|
||||
CompilerInvocation &InitInvok,
|
||||
llvm::StringSet<> &Modules,
|
||||
bool IsBaseline = false) {
|
||||
InitInvok.setMainExecutablePath(fs::getMainExecutable(Main,
|
||||
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
|
||||
InitInvok.setModuleName("swift_ide_test");
|
||||
setSDKPath(InitInvok, IsBaseline);
|
||||
|
||||
if (!options::Triple.empty())
|
||||
InitInvok.setTargetTriple(options::Triple);
|
||||
@@ -2308,7 +2332,7 @@ static int prepareForDump(const char *Main,
|
||||
}
|
||||
if (!isValid) {
|
||||
llvm::errs() << "Unsupported Swift Version.\n";
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2316,28 +2340,31 @@ static int prepareForDump(const char *Main,
|
||||
InitInvok.setRuntimeResourcePath(options::ResourceDir);
|
||||
}
|
||||
std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths;
|
||||
for (const auto &path : options::FrameworkPaths) {
|
||||
FramePaths.push_back({path, /*isSystem=*/false});
|
||||
}
|
||||
for (const auto &path : options::CCSystemFrameworkPaths) {
|
||||
FramePaths.push_back({path, /*isSystem=*/true});
|
||||
}
|
||||
InitInvok.setFrameworkSearchPaths(FramePaths);
|
||||
if (IsBaseline) {
|
||||
for (const auto &path : options::BaselineFrameworkPaths) {
|
||||
FramePaths.push_back({path, /*isSystem=*/false});
|
||||
}
|
||||
InitInvok.setImportSearchPaths(options::BaselineModuleInputPaths);
|
||||
} else {
|
||||
for (const auto &path : options::FrameworkPaths) {
|
||||
FramePaths.push_back({path, /*isSystem=*/false});
|
||||
}
|
||||
InitInvok.setImportSearchPaths(options::ModuleInputPaths);
|
||||
}
|
||||
InitInvok.setFrameworkSearchPaths(FramePaths);
|
||||
if (!options::ModuleList.empty()) {
|
||||
if (readFileLineByLine(options::ModuleList, Modules))
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
for (auto M : options::ModuleNames) {
|
||||
Modules.insert(M);
|
||||
}
|
||||
if (Modules.empty()) {
|
||||
llvm::errs() << "Need to specify -include-all or -module <name>\n";
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2406,6 +2433,11 @@ static SDKNodeRoot *getSDKRoot(const char *Main, SDKContext &Ctx,
|
||||
return getSDKNodeRoot(Ctx, Invok, Modules, Opts);
|
||||
}
|
||||
|
||||
static bool hasBaselineInput() {
|
||||
return !options::BaselineModuleInputPaths.empty() ||
|
||||
!options::BaselineFrameworkPaths.empty() || !options::BaselineSDK.empty();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
PROGRAM_START(argc, argv);
|
||||
INITIALIZE_LLVM();
|
||||
@@ -2428,7 +2460,7 @@ int main(int argc, char *argv[]) {
|
||||
case ActionType::MigratorGen:
|
||||
case ActionType::DiagnoseSDKs: {
|
||||
bool CompareJson = options::SDKJsonPaths.size() == 2;
|
||||
if (!CompareJson && options::BaselineModuleInputPaths.empty()) {
|
||||
if (!CompareJson && !hasBaselineInput()) {
|
||||
llvm::errs() << "Only two SDK versions can be compared\n";
|
||||
llvm::cl::PrintHelpMessage();
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user